[Code] Export integration components (#47636) (#47880)

* Expose CodeBlockPanel component

This separates the current CodeBlock component into two:
* CodeBlock, which simply renders the code view without
padding/margin
* CodeBlockPanel which wraps the CodeBlock in an EUIPanel and allows
overrides

It seems like APM will want to use the former for their integration,
while the latter is currently used internally by Code. It's very simple,
though, and could absolutely be inlined.

* Update demo page to use CodeBlock

This has no styling, and so a header could go right against it, it
could be shown/hidden distinct from the header, etc.

* Export our current integration components from main index

Adds a 'shared' manifest that does all the reaching in; the main one
just re-exports that.

* Move shared exports to the frontend manifest

This was incorrectly placed a level too high, in the plugin itself.

* Rename to better reflect relationship

CodeBlockPanel = EuiPanel + CodeBlock

* Distinguish monaco CSS overrides with page-specific layout
This commit is contained in:
Ryland Herrick 2019-10-10 15:12:06 -05:00 committed by GitHub
parent 297ef13e96
commit 2fe225009d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 69 additions and 38 deletions

View file

@ -4,9 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { EuiPanel } from '@elastic/eui';
import { editor, IRange } from 'monaco-editor';
import React from 'react';
import React, { createRef } from 'react';
import { ResizeChecker } from '../shared/resize_checker';
import { monaco } from '../../monaco/monaco';
@ -19,7 +18,6 @@ export interface Position {
export interface Props {
content: string;
header: React.ReactNode;
language: string;
highlightRanges: IRange[];
onClick: (event: Position) => void;
@ -29,12 +27,10 @@ export interface Props {
* @param lineIndex The index of the given line (0-indexed)
*/
lineNumber: (lineIndex: number) => string;
className?: string;
}
export class CodeBlock extends React.PureComponent<Props> {
static defaultProps = {
header: undefined,
folding: false,
highlightRanges: [],
language: 'text',
@ -42,7 +38,7 @@ export class CodeBlock extends React.PureComponent<Props> {
onClick: () => {},
};
private el: HTMLDivElement | null = null;
private el = createRef<HTMLDivElement>();
private ed?: editor.IStandaloneCodeEditor;
private resizeChecker?: ResizeChecker;
private currentHighlightDecorations: string[] = [];
@ -50,7 +46,7 @@ export class CodeBlock extends React.PureComponent<Props> {
public async componentDidMount() {
const { content, highlightRanges, language, onClick } = this.props;
if (this.el) {
if (this.el.current) {
await this.tryLoadFile(content, language);
this.ed!.onMouseDown((e: editor.IEditorMouseEvent) => {
if (
@ -80,7 +76,7 @@ export class CodeBlock extends React.PureComponent<Props> {
});
this.currentHighlightDecorations = this.ed!.deltaDecorations([], decorations);
}
this.resizeChecker = new ResizeChecker(this.el!);
this.resizeChecker = new ResizeChecker(this.el.current!);
this.resizeChecker.on('resize', () => {
setTimeout(() => {
this.ed!.layout();
@ -99,7 +95,7 @@ export class CodeBlock extends React.PureComponent<Props> {
}
private loadFile(code: string, language: string = 'text') {
this.ed = monaco.editor.create(this.el!, {
this.ed = monaco.editor.create(this.el.current!, {
value: code,
language,
lineNumbers: this.lineNumber,
@ -160,15 +156,9 @@ export class CodeBlock extends React.PureComponent<Props> {
}
public render() {
const { className, header } = this.props;
const height = this.lines.length * 18;
return (
<EuiPanel paddingSize="s" className={className}>
{header}
<div ref={r => (this.el = r)} style={{ height }} />
</EuiPanel>
);
return <div ref={this.el} className="codeContainer__monaco" style={{ height }} />;
}
private lineNumber = (lineIndex: number) => this.props.lineNumber(lineIndex - 1);

View file

@ -0,0 +1,24 @@
/*
* 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, { ReactNode } from 'react';
import { EuiPanel } from '@elastic/eui';
import { CodeBlock, Props as CodeBlockProps } from './code_block';
export interface Props extends CodeBlockProps {
className?: string;
header?: ReactNode;
}
export const CodeBlockPanel = ({ className, header, ...rest }: Props) => (
<EuiPanel paddingSize="s" className={className}>
{header}
<CodeBlock {...rest} />
</EuiPanel>
);
CodeBlockPanel.defaultProps = CodeBlock.defaultProps;

View file

@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export { CodeBlock, Position, Props as CodeBlockProps } from './code_block';
export { CodeBlockPanel, Props as CodeBlockPanelProps } from './code_block_panel';

View file

@ -175,7 +175,7 @@ export class EditorComponent extends React.Component<IProps> {
/>
<div
tabIndex={0}
className="codeContainer__editor"
className="codeContainer__editor codeContainer__monaco"
id="mainEditor"
hidden={this.props.hidden}
/>

View file

@ -19,7 +19,7 @@ import React from 'react';
import { parseSchema } from '../../../common/uri_util';
import { GroupedFileResults, GroupedRepoResults } from '../../actions';
import { history } from '../../utils/url';
import { CodeBlock, Position } from '../codeblock/codeblock';
import { CodeBlockPanel, Position } from '../code_block';
interface Props {
isLoading: boolean;
@ -123,7 +123,7 @@ export class ReferencesPanel extends React.Component<Props, State> {
);
return (
<CodeBlock
<CodeBlockPanel
className="referencesPanel__code-block"
key={key}
header={header}

View file

@ -9,7 +9,7 @@ import { EuiButtonEmpty, EuiPopover, EuiText } from '@elastic/eui';
import { RepoSelector } from './repo_selector';
interface Props {
export interface Props {
onRepoSelect: (repo: string) => void;
onImportSuccess: (repo: string) => void;
repos: string[];

View file

@ -5,9 +5,9 @@
*/
import React from 'react';
import { EuiFlexGroup, EuiText } from '@elastic/eui';
import { EuiFlexGroup, EuiPanel, EuiText } from '@elastic/eui';
import { CodeBlock } from '../codeblock/codeblock';
import { CodeBlock } from '../code_block';
import { history } from '../../utils/url';
import { FrameHeader } from './frame_header';
import { RepoTitle } from './repo_title';
@ -21,7 +21,7 @@ const associateToService = (frame: Frame) => (repo: string) =>
const handleImport = (repo: string) => alert(`import done: ${repo}`);
export const Integrations = () => (
<div className="codeContainer__root codeIntegrations__container">
<div className="codeIntegrations__container">
{frames.map(frame => {
const { fileName, lineNumber } = frame;
const key = `${fileName}#L${lineNumber}`;
@ -35,18 +35,14 @@ export const Integrations = () => (
return (
<div key={key} className="codeIntegrations__frame">
<RepoTitle uri={snippet.uri} />
<CodeBlock
content={content}
header={
<FrameHeader
fileName={fileName}
lineNumber={lineNumber}
onClick={() => history.push(fileUrl)}
/>
}
language={language}
lineNumber={i => lineMapping[i]}
/>
<EuiPanel paddingSize="s">
<FrameHeader
fileName={fileName}
lineNumber={lineNumber}
onClick={() => history.push(fileUrl)}
/>
<CodeBlock content={content} language={language} lineNumber={i => lineMapping[i]} />
</EuiPanel>
</div>
);
}

View file

@ -11,7 +11,7 @@ import { Link } from 'react-router-dom';
import { RepositoryUtils } from '../../../common/repository_utils';
import { history } from '../../utils/url';
import { CodeBlock, Position } from '../codeblock/codeblock';
import { CodeBlockPanel, Position } from '../code_block';
interface Props {
query: string;
@ -71,7 +71,7 @@ export class CodeResult extends React.PureComponent<Props> {
</Link>
</EuiText>
</EuiFlexGroup>
<CodeBlock
<CodeBlockPanel
key={`code${key}`}
className="codeResult__code-block"
content={content}

View file

@ -12,6 +12,8 @@ export function plugin(initializerContext: PluginInitializerContext) {
return new Plugin(initializerContext);
}
export * from './shared';
// This is the shim to legacy platform
const p = plugin({} as PluginInitializerContext);
p.start(npStart.core);

View file

@ -1,4 +1,4 @@
.codeContainer__root {
.codeContainer__monaco {
.monaco-editor .cursors-layer > .cursor {
display: none !important;
}

View file

@ -0,0 +1,11 @@
/*
* 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 './components/code_block';
export {
CodeIntegrator,
Props as CodeIntegratorProps,
} from './components/integrations/code_integrator';