[Canvas] ArgTemplateForm refactor. (#106637)

* Refactored `ArgTemplateForm`.

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Yaroslav Kuznietsov 2021-08-10 09:15:04 +03:00 committed by GitHub
parent 6fafe87627
commit 7366df9454
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 89 additions and 95 deletions

View file

@ -1,95 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { compose, withPropsOnChange, withProps } from 'recompose';
import { RenderToDom } from '../render_to_dom';
import { ExpressionFormHandlers } from '../../../common/lib/expression_form_handlers';
class ArgTemplateFormComponent extends React.Component {
static propTypes = {
template: PropTypes.func,
argumentProps: PropTypes.shape({
valueMissing: PropTypes.bool,
label: PropTypes.string,
setLabel: PropTypes.func.isRequired,
expand: PropTypes.bool,
setExpand: PropTypes.func,
onValueRemove: PropTypes.func,
resetErrorState: PropTypes.func.isRequired,
renderError: PropTypes.func.isRequired,
}),
handlers: PropTypes.object.isRequired,
error: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]).isRequired,
errorTemplate: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired,
};
UNSAFE_componentWillUpdate(prevProps) {
//see if error state changed
if (this.props.error !== prevProps.error) {
this.props.handlers.destroy();
}
}
componentDidUpdate() {
if (this.props.error) {
return this._renderErrorTemplate();
}
this._renderTemplate(this._domNode);
}
componentWillUnmount() {
this.props.handlers.destroy();
}
_domNode = null;
_renderTemplate = (domNode) => {
const { template, argumentProps, handlers } = this.props;
if (template) {
return template(domNode, argumentProps, handlers);
}
};
_renderErrorTemplate = () => {
const { errorTemplate, argumentProps } = this.props;
return React.createElement(errorTemplate, argumentProps);
};
render() {
const { template, error } = this.props;
if (error) {
return this._renderErrorTemplate();
}
if (!template) {
return null;
}
return (
<RenderToDom
render={(domNode) => {
this._domNode = domNode;
this._renderTemplate(domNode);
}}
/>
);
}
}
export const ArgTemplateForm = compose(
withPropsOnChange(
() => false,
() => ({
expressionFormHandlers: new ExpressionFormHandlers(),
})
),
withProps(({ handlers, expressionFormHandlers }) => ({
handlers: Object.assign(expressionFormHandlers, handlers),
}))
)(ArgTemplateFormComponent);

View file

@ -0,0 +1,89 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { useState, useEffect, useCallback, useRef } from 'react';
import usePrevious from 'react-use/lib/usePrevious';
import { RenderToDom } from '../render_to_dom';
import { ExpressionFormHandlers } from '../../../common/lib/expression_form_handlers';
interface ArgTemplateFormProps {
template?: (
domNode: HTMLElement,
config: ArgTemplateFormProps['argumentProps'],
handlers: ArgTemplateFormProps['handlers']
) => void;
argumentProps: {
valueMissing?: boolean;
label?: string;
setLabel: (label: string) => void;
expand?: boolean;
setExpand?: (expand: boolean) => void;
onValueRemove?: (argName: string, argIndex: string) => void;
resetErrorState: () => void;
renderError: () => void;
};
handlers?: { [key: string]: (...args: any[]) => any };
error?: unknown;
errorTemplate: React.FunctionComponent<ArgTemplateFormProps['argumentProps']>;
}
const mergeWithFormHandlers = (handlers: ArgTemplateFormProps['handlers']) =>
Object.assign(new ExpressionFormHandlers(), handlers);
export const ArgTemplateForm: React.FunctionComponent<ArgTemplateFormProps> = ({
template,
argumentProps,
handlers,
error,
errorTemplate,
}) => {
const [updatedHandlers, setHandlers] = useState(mergeWithFormHandlers(handlers));
const previousError = usePrevious(error);
const domNodeRef = useRef<HTMLElement>();
const renderTemplate = useCallback(
(domNode) => template && template(domNode, argumentProps, updatedHandlers),
[template, argumentProps, updatedHandlers]
);
const renderErrorTemplate = useCallback(() => React.createElement(errorTemplate, argumentProps), [
errorTemplate,
argumentProps,
]);
useEffect(() => {
setHandlers(mergeWithFormHandlers(handlers));
}, [handlers]);
useEffect(() => {
if (previousError !== error) {
updatedHandlers.destroy();
}
}, [previousError, error, updatedHandlers]);
useEffect(() => {
if (!error) {
renderTemplate(domNodeRef.current);
}
}, [error, renderTemplate, domNodeRef]);
if (error) {
return renderErrorTemplate();
}
if (!template) {
return null;
}
return (
<RenderToDom
render={(domNode) => {
domNodeRef.current = domNode;
renderTemplate(domNode);
}}
/>
);
};