mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
* Added formatnumber and formatdate transform UIs * Added rounddate transform * Changed default custom format * Changed to UTC date * Fixed ts error * Fixed help text * Added type def for arguments * Added types for tranforms * Added snapshots * Fixed prop
This commit is contained in:
parent
cf6d86c295
commit
79cea1f906
21 changed files with 621 additions and 53 deletions
|
@ -8,7 +8,7 @@ import moment from 'moment';
|
|||
import { ExpressionFunction } from 'src/legacy/core_plugins/interpreter/public';
|
||||
import { getFunctionHelp } from '../../strings';
|
||||
|
||||
interface Arguments {
|
||||
export interface Arguments {
|
||||
format: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import numeral from '@elastic/numeral';
|
|||
import { ExpressionFunction } from 'src/legacy/core_plugins/interpreter/public';
|
||||
import { getFunctionHelp } from '../../strings';
|
||||
|
||||
interface Arguments {
|
||||
export interface Arguments {
|
||||
format: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import moment from 'moment';
|
|||
import { ExpressionFunction } from 'src/legacy/core_plugins/interpreter/public';
|
||||
import { getFunctionHelp } from '../../strings';
|
||||
|
||||
interface Arguments {
|
||||
export interface Arguments {
|
||||
format: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots arguments/DateFormat with custom format 1`] = `
|
||||
Array [
|
||||
<div
|
||||
className="euiFormControlLayout euiFormControlLayout--compressed"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<select
|
||||
className="euiSelect euiSelect--compressed"
|
||||
id="DateFormatExample3"
|
||||
onChange={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
value="custom"
|
||||
>
|
||||
<option
|
||||
value="l"
|
||||
>
|
||||
Shorthand
|
||||
</option>
|
||||
<option
|
||||
value="x"
|
||||
>
|
||||
Unix
|
||||
</option>
|
||||
<option
|
||||
value="LLL"
|
||||
>
|
||||
Longhand
|
||||
</option>
|
||||
<option
|
||||
value="custom"
|
||||
>
|
||||
Custom
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
className="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
|
||||
>
|
||||
<span
|
||||
className="euiFormControlLayoutCustomIcon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiIcon-isLoading euiFormControlLayoutCustomIcon__icon"
|
||||
focusable="false"
|
||||
height={16}
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
className="euiSpacer euiSpacer--s"
|
||||
/>,
|
||||
<div
|
||||
className="euiFormControlLayout euiFormControlLayout--compressed"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<input
|
||||
className="euiFieldText euiFieldText--compressed"
|
||||
onChange={[Function]}
|
||||
placeholder="M/D/YY h:ma"
|
||||
type="text"
|
||||
value="MM/DD/YYYY"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Storyshots arguments/DateFormat with no format 1`] = `
|
||||
Array [
|
||||
<div
|
||||
className="euiFormControlLayout euiFormControlLayout--compressed"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<select
|
||||
className="euiSelect euiSelect--compressed"
|
||||
id="DateFormatExample1"
|
||||
onChange={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
value="custom"
|
||||
>
|
||||
<option
|
||||
value="l"
|
||||
>
|
||||
Shorthand
|
||||
</option>
|
||||
<option
|
||||
value="x"
|
||||
>
|
||||
Unix
|
||||
</option>
|
||||
<option
|
||||
value="LLL"
|
||||
>
|
||||
Longhand
|
||||
</option>
|
||||
<option
|
||||
value="custom"
|
||||
>
|
||||
Custom
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
className="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
|
||||
>
|
||||
<span
|
||||
className="euiFormControlLayoutCustomIcon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiIcon-isLoading euiFormControlLayoutCustomIcon__icon"
|
||||
focusable="false"
|
||||
height={16}
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
className="euiSpacer euiSpacer--s"
|
||||
/>,
|
||||
<div
|
||||
className="euiFormControlLayout euiFormControlLayout--compressed"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<input
|
||||
className="euiFieldText euiFieldText--compressed"
|
||||
onChange={[Function]}
|
||||
placeholder="M/D/YY h:ma"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Storyshots arguments/DateFormat with preset format 1`] = `
|
||||
<div
|
||||
className="euiFormControlLayout euiFormControlLayout--compressed"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<select
|
||||
className="euiSelect euiSelect--compressed"
|
||||
id="DateFormatExample2"
|
||||
onChange={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
value="LLL"
|
||||
>
|
||||
<option
|
||||
value="l"
|
||||
>
|
||||
Shorthand
|
||||
</option>
|
||||
<option
|
||||
value="x"
|
||||
>
|
||||
Unix
|
||||
</option>
|
||||
<option
|
||||
value="LLL"
|
||||
>
|
||||
Longhand
|
||||
</option>
|
||||
<option
|
||||
value="custom"
|
||||
>
|
||||
Custom
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
className="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
|
||||
>
|
||||
<span
|
||||
className="euiFormControlLayoutCustomIcon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiIcon-isLoading euiFormControlLayoutCustomIcon__icon"
|
||||
focusable="false"
|
||||
height={16}
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { DateFormatArgInput } from '../date_format';
|
||||
|
||||
const dateFormats = [
|
||||
{ value: 'l', text: 'Shorthand' },
|
||||
{ value: 'x', text: 'Unix' },
|
||||
{ value: 'LLL', text: 'Longhand' },
|
||||
];
|
||||
|
||||
storiesOf('arguments/DateFormat', module)
|
||||
.add('with no format', () => (
|
||||
<DateFormatArgInput
|
||||
dateFormats={dateFormats}
|
||||
onValueChange={action('onValueChange')}
|
||||
argValue=""
|
||||
argId="DateFormatExample1"
|
||||
renderError={action('renderError')}
|
||||
/>
|
||||
))
|
||||
.add('with preset format', () => (
|
||||
<DateFormatArgInput
|
||||
dateFormats={dateFormats}
|
||||
onValueChange={action('onValueChange')}
|
||||
argValue="LLL"
|
||||
argId="DateFormatExample2"
|
||||
renderError={action('renderError')}
|
||||
/>
|
||||
))
|
||||
.add('with custom format', () => (
|
||||
<DateFormatArgInput
|
||||
dateFormats={dateFormats}
|
||||
onValueChange={action('onValueChange')}
|
||||
argValue="MM/DD/YYYY"
|
||||
argId="DateFormatExample3"
|
||||
renderError={action('renderError')}
|
||||
/>
|
||||
));
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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, { FunctionComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormatSelect } from '../../../../public/components/format_select/format_select';
|
||||
import { ArgumentProps } from '../../../../types/arguments';
|
||||
|
||||
interface DateFormatOption {
|
||||
/** A MomentJS format string */
|
||||
value: string;
|
||||
/** The name to display for the format */
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface Props extends ArgumentProps {
|
||||
/** An array of number formats options */
|
||||
dateFormats: DateFormatOption[];
|
||||
/** The handler to invoke when value changes */
|
||||
onValueChange: (value: string) => void;
|
||||
/** The value of the argument */
|
||||
argValue: string;
|
||||
/** The ID for the argument */
|
||||
argId: string;
|
||||
}
|
||||
|
||||
export const DateFormatArgInput: FunctionComponent<Props> = ({
|
||||
dateFormats,
|
||||
onValueChange,
|
||||
argValue,
|
||||
argId,
|
||||
}) => (
|
||||
<FormatSelect
|
||||
argId={argId}
|
||||
argValue={argValue}
|
||||
formatOptions={dateFormats}
|
||||
onValueChange={onValueChange}
|
||||
defaultCustomFormat="M/D/YY h:ma"
|
||||
/>
|
||||
);
|
||||
|
||||
DateFormatArgInput.propTypes = {
|
||||
dateFormats: PropTypes.arrayOf(
|
||||
PropTypes.shape({ value: PropTypes.string, text: PropTypes.string })
|
||||
).isRequired,
|
||||
onValueChange: PropTypes.func.isRequired,
|
||||
argValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]).isRequired,
|
||||
argId: PropTypes.string.isRequired,
|
||||
};
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 { compose, withProps } from 'recompose';
|
||||
import moment from 'moment';
|
||||
import { DateFormatArgInput as Component, Props as ComponentProps } from './date_format';
|
||||
import { AdvancedSettings } from '../../../../public/lib/kibana_advanced_settings';
|
||||
// @ts-ignore untyped local lib
|
||||
import { templateFromReactComponent } from '../../../../public/lib/template_from_react_component';
|
||||
import { ArgumentFactory } from '../../../../types/arguments';
|
||||
|
||||
const formatMap = {
|
||||
DEFAULT: AdvancedSettings.get('dateFormat'),
|
||||
NANOS: AdvancedSettings.get('dateNanosFormat'),
|
||||
ISO8601: '',
|
||||
LOCAL_LONG: 'LLLL',
|
||||
LOCAL_SHORT: 'LLL',
|
||||
LOCAL_DATE: 'l',
|
||||
LOCAL_TIME_WITH_SECONDS: 'LTS',
|
||||
};
|
||||
|
||||
const now = moment();
|
||||
|
||||
const dateFormats = Object.values(formatMap).map(format => ({
|
||||
value: format,
|
||||
text: moment.utc(now).format(format),
|
||||
}));
|
||||
|
||||
export const DateFormatArgInput = compose<ComponentProps, null>(withProps({ dateFormats }))(
|
||||
Component
|
||||
);
|
||||
|
||||
export const dateFormat: ArgumentFactory<ComponentProps> = () => ({
|
||||
name: 'dateFormat',
|
||||
displayName: 'Date Format',
|
||||
help: 'Select or enter a MomentJS format',
|
||||
simpleTemplate: templateFromReactComponent(DateFormatArgInput),
|
||||
});
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { axisConfig } from './axis_config';
|
||||
import { datacolumn } from './datacolumn';
|
||||
import { dateFormat } from './date_format';
|
||||
import { filterGroup } from './filter_group';
|
||||
import { imageUpload } from './image_upload';
|
||||
import { number } from './number';
|
||||
|
@ -22,6 +23,7 @@ import { toggle } from './toggle';
|
|||
export const args = [
|
||||
axisConfig,
|
||||
datacolumn,
|
||||
dateFormat,
|
||||
filterGroup,
|
||||
imageUpload,
|
||||
number,
|
||||
|
|
|
@ -13,7 +13,7 @@ Array [
|
|||
id="NumberFormatExample3"
|
||||
onChange={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
value=""
|
||||
value="custom"
|
||||
>
|
||||
<option
|
||||
value="0.0[000]"
|
||||
|
@ -41,7 +41,7 @@ Array [
|
|||
Bytes
|
||||
</option>
|
||||
<option
|
||||
value=""
|
||||
value="custom"
|
||||
>
|
||||
Custom
|
||||
</option>
|
||||
|
@ -100,7 +100,7 @@ Array [
|
|||
id="NumberFormatExample1"
|
||||
onChange={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
value=""
|
||||
value="custom"
|
||||
>
|
||||
<option
|
||||
value="0.0[000]"
|
||||
|
@ -128,7 +128,7 @@ Array [
|
|||
Bytes
|
||||
</option>
|
||||
<option
|
||||
value=""
|
||||
value="custom"
|
||||
>
|
||||
Custom
|
||||
</option>
|
||||
|
@ -214,7 +214,7 @@ exports[`Storyshots arguments/NumberFormat with preset format 1`] = `
|
|||
Bytes
|
||||
</option>
|
||||
<option
|
||||
value=""
|
||||
value="custom"
|
||||
>
|
||||
Custom
|
||||
</option>
|
||||
|
|
|
@ -23,6 +23,7 @@ storiesOf('arguments/NumberFormat', module)
|
|||
onValueChange={action('onValueChange')}
|
||||
argValue=""
|
||||
argId="NumberFormatExample1"
|
||||
renderError={action('renderError')}
|
||||
/>
|
||||
))
|
||||
.add('with preset format', () => (
|
||||
|
@ -31,6 +32,7 @@ storiesOf('arguments/NumberFormat', module)
|
|||
onValueChange={action('onValueChange')}
|
||||
argValue="$0.00"
|
||||
argId="NumberFormatExample2"
|
||||
renderError={action('renderError')}
|
||||
/>
|
||||
))
|
||||
.add('with custom format', () => (
|
||||
|
@ -39,5 +41,6 @@ storiesOf('arguments/NumberFormat', module)
|
|||
onValueChange={action('onValueChange')}
|
||||
argValue="0.0[000]a"
|
||||
argId="NumberFormatExample3"
|
||||
renderError={action('renderError')}
|
||||
/>
|
||||
));
|
||||
|
|
|
@ -9,6 +9,7 @@ import { NumberFormatArgInput as Component, Props as ComponentProps } from './nu
|
|||
import { AdvancedSettings } from '../../../../public/lib/kibana_advanced_settings';
|
||||
// @ts-ignore untyped local lib
|
||||
import { templateFromReactComponent } from '../../../../public/lib/template_from_react_component';
|
||||
import { ArgumentFactory } from '../../../../types/arguments';
|
||||
|
||||
const formatMap = {
|
||||
NUMBER: AdvancedSettings.get('format:number:defaultPattern'),
|
||||
|
@ -30,7 +31,7 @@ export const NumberFormatArgInput = compose<ComponentProps, null>(withProps({ nu
|
|||
Component
|
||||
);
|
||||
|
||||
export const numberFormat = () => ({
|
||||
export const numberFormat: ArgumentFactory<ComponentProps> = () => ({
|
||||
name: 'numberFormat',
|
||||
displayName: 'Number Format',
|
||||
help: 'Select or enter a valid NumeralJS format',
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { Fragment, ChangeEvent, FunctionComponent } from 'react';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { EuiSelect, EuiFieldText, EuiSpacer } from '@elastic/eui';
|
||||
import { FormatSelect } from '../../../../public/components/format_select/format_select';
|
||||
import { ArgumentProps } from '../../../../types/arguments';
|
||||
|
||||
interface NumberFormatOption {
|
||||
/** A NumeralJS format string */
|
||||
|
@ -15,7 +16,7 @@ interface NumberFormatOption {
|
|||
text: string;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
export interface Props extends ArgumentProps {
|
||||
/** An array of number formats options */
|
||||
numberFormats: NumberFormatOption[];
|
||||
/** The handler to invoke when value changes */
|
||||
|
@ -31,42 +32,20 @@ export const NumberFormatArgInput: FunctionComponent<Props> = ({
|
|||
onValueChange,
|
||||
argValue,
|
||||
argId,
|
||||
}) => {
|
||||
const formatOptions = numberFormats.concat({ value: '', text: 'Custom' });
|
||||
const handleTextChange = (ev: ChangeEvent<HTMLInputElement>) => onValueChange(ev.target.value);
|
||||
const handleSelectChange = (ev: ChangeEvent<HTMLSelectElement>) => {
|
||||
const { value } = formatOptions[ev.target.selectedIndex];
|
||||
return onValueChange(value || '0.0a');
|
||||
};
|
||||
|
||||
// checks if the argValue is one of the preset formats
|
||||
const isCustomFormat = !argValue || !formatOptions.map(({ value }) => value).includes(argValue);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiSelect
|
||||
compressed
|
||||
id={argId}
|
||||
value={isCustomFormat ? '' : argValue}
|
||||
options={formatOptions}
|
||||
onChange={handleSelectChange}
|
||||
/>
|
||||
{isCustomFormat && (
|
||||
<Fragment>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiFieldText
|
||||
placeholder="0.0a"
|
||||
value={argValue}
|
||||
compressed
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
}) => (
|
||||
<FormatSelect
|
||||
argId={argId}
|
||||
argValue={argValue}
|
||||
formatOptions={numberFormats}
|
||||
onValueChange={onValueChange}
|
||||
defaultCustomFormat="0.0a"
|
||||
/>
|
||||
);
|
||||
|
||||
NumberFormatArgInput.propTypes = {
|
||||
numberFormats: PropTypes.arrayOf(
|
||||
PropTypes.shape({ value: PropTypes.string, text: PropTypes.string })
|
||||
).isRequired,
|
||||
onValueChange: PropTypes.func.isRequired,
|
||||
argValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]).isRequired,
|
||||
argId: PropTypes.string.isRequired,
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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 { TransformFactory } from '../../../types/transforms';
|
||||
import { Arguments } from '../../functions/common/formatdate';
|
||||
|
||||
export const formatdate: TransformFactory<Arguments> = () => ({
|
||||
name: 'formatdate',
|
||||
displayName: 'Date format',
|
||||
args: [
|
||||
{
|
||||
name: 'format',
|
||||
displayName: 'Format',
|
||||
argType: 'dateformat',
|
||||
},
|
||||
],
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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 { TransformFactory } from '../../../types/transforms';
|
||||
import { Arguments } from '../../functions/common/formatnumber';
|
||||
|
||||
export const formatnumber: TransformFactory<Arguments> = () => ({
|
||||
name: 'formatnumber',
|
||||
displayName: 'Number format',
|
||||
args: [
|
||||
{
|
||||
name: 'format',
|
||||
displayName: 'Format',
|
||||
argType: 'numberformat',
|
||||
},
|
||||
],
|
||||
});
|
|
@ -4,6 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { formatdate } from './formatdate';
|
||||
import { formatnumber } from './formatnumber';
|
||||
import { rounddate } from './rounddate';
|
||||
import { sort } from './sort';
|
||||
|
||||
export const transformSpecs = [sort];
|
||||
export const transformSpecs = [formatdate, formatnumber, rounddate, sort];
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { TransformFactory } from '../../../types/transforms';
|
||||
import { Arguments } from '../../functions/common/rounddate';
|
||||
|
||||
export const rounddate: TransformFactory<Arguments> = () => ({
|
||||
name: 'rounddate',
|
||||
displayName: 'Round date',
|
||||
args: [
|
||||
{
|
||||
name: 'format',
|
||||
displayName: 'Format',
|
||||
argType: 'dateformat',
|
||||
help: 'Select or enter a MomentJS format to round the date',
|
||||
},
|
||||
],
|
||||
});
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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, { Fragment, PureComponent, ChangeEvent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { EuiSelect, EuiSpacer, EuiFieldText } from '@elastic/eui';
|
||||
|
||||
interface Props {
|
||||
/** The ID of the argument form */
|
||||
argId: string;
|
||||
/** The current format string value */
|
||||
argValue: string;
|
||||
/** The preset format options to populate the select control */
|
||||
formatOptions: Array<{ value: string; text: string }>;
|
||||
/** The default custom format to initially populate the text field with */
|
||||
defaultCustomFormat: string;
|
||||
/** The handler to commit the new value */
|
||||
onValueChange: (value: string) => void;
|
||||
}
|
||||
|
||||
export class FormatSelect extends PureComponent<Props> {
|
||||
static propTypes = {
|
||||
argId: PropTypes.string,
|
||||
argValue: PropTypes.string,
|
||||
formatOptions: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
value: PropTypes.string,
|
||||
text: PropTypes.string,
|
||||
})
|
||||
).isRequired,
|
||||
onValueChange: PropTypes.func,
|
||||
};
|
||||
|
||||
state = {
|
||||
isCustomFormat: !this.props.formatOptions
|
||||
.map(({ value }) => value)
|
||||
.includes(this.props.argValue),
|
||||
};
|
||||
|
||||
_options = this.props.formatOptions.concat({ value: 'custom', text: 'Custom' });
|
||||
|
||||
_handleTextChange = (ev: ChangeEvent<HTMLInputElement>) =>
|
||||
this.props.onValueChange(ev.target.value);
|
||||
|
||||
_handleSelectChange = (ev: ChangeEvent<HTMLSelectElement>) => {
|
||||
const { onValueChange, defaultCustomFormat } = this.props;
|
||||
const { value } = this._options[ev.target.selectedIndex];
|
||||
|
||||
if (value === 'custom') {
|
||||
this.setState({ isCustomFormat: true });
|
||||
return onValueChange(defaultCustomFormat);
|
||||
}
|
||||
|
||||
if (this.state.isCustomFormat) {
|
||||
this.setState({ isCustomFormat: false });
|
||||
}
|
||||
|
||||
return onValueChange(value);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { argId, argValue, defaultCustomFormat } = this.props;
|
||||
const { isCustomFormat } = this.state;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiSelect
|
||||
compressed
|
||||
id={argId}
|
||||
value={isCustomFormat ? 'custom' : argValue}
|
||||
options={this._options}
|
||||
onChange={this._handleSelectChange}
|
||||
/>
|
||||
{isCustomFormat && (
|
||||
<Fragment>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiFieldText
|
||||
placeholder={defaultCustomFormat}
|
||||
value={argValue}
|
||||
compressed
|
||||
onChange={this._handleTextChange}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* 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 { FormatSelect } from './format_select';
|
|
@ -8,16 +8,12 @@ import React, { ComponentType, FunctionComponent } from 'react';
|
|||
import { unmountComponentAtNode, render } from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ErrorBoundary } from '../components/enhance/error_boundary';
|
||||
import { ArgumentHandlers } from '../../types/arguments';
|
||||
|
||||
interface Props {
|
||||
renderError: Function;
|
||||
}
|
||||
|
||||
interface Handlers {
|
||||
done: () => void;
|
||||
onDestroy: (fn: () => void) => void;
|
||||
}
|
||||
|
||||
export const templateFromReactComponent = (Component: ComponentType<any>) => {
|
||||
const WrappedComponent: FunctionComponent<Props> = props => (
|
||||
<ErrorBoundary>
|
||||
|
@ -36,7 +32,7 @@ export const templateFromReactComponent = (Component: ComponentType<any>) => {
|
|||
renderError: PropTypes.func,
|
||||
};
|
||||
|
||||
return (domNode: Element, config: Props, handlers: Handlers) => {
|
||||
return (domNode: HTMLElement, config: Props, handlers: ArgumentHandlers) => {
|
||||
try {
|
||||
const el = React.createElement(WrappedComponent, config);
|
||||
render(el, domNode, () => {
|
||||
|
|
56
x-pack/legacy/plugins/canvas/types/arguments.ts
Normal file
56
x-pack/legacy/plugins/canvas/types/arguments.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
type GenericCallback = (callback: () => void) => void;
|
||||
|
||||
export interface ArgumentProps {
|
||||
/** Handler to invoke when error has thrown in the argument form */
|
||||
renderError: () => void;
|
||||
}
|
||||
|
||||
export interface ArgumentHandlers {
|
||||
/** Handler to invoke when an argument form has finished rendering */
|
||||
done: () => void;
|
||||
/** Handler to invoke when an argument form is removed */
|
||||
onDestroy: GenericCallback;
|
||||
}
|
||||
|
||||
export interface ArgumentSpec<ArgumentConfig = {}> {
|
||||
/** The argument type */
|
||||
name: string;
|
||||
/** The name to display */
|
||||
displayName: string;
|
||||
/** A description of what is rendered */
|
||||
help: string;
|
||||
/**
|
||||
* A function that renders a compact, non-collapsible argument form
|
||||
* If template is also provided, then this form goes in the accordion header
|
||||
* */
|
||||
simpleTemplate?: (
|
||||
domNode: HTMLElement,
|
||||
config: ArgumentConfig,
|
||||
handlers: ArgumentHandlers
|
||||
) => void;
|
||||
/**
|
||||
* A function that renders a complex/large argument
|
||||
* This is nested in an accordian so it can be expanded/collapsed
|
||||
*/
|
||||
template?: (domNode: HTMLElement, config: ArgumentConfig, handlers: ArgumentHandlers) => void;
|
||||
}
|
||||
|
||||
export type ArgumentFactory<ArgumentConfig = {}> = () => ArgumentSpec<ArgumentConfig>;
|
||||
|
||||
// Settings for the argument to display in the sidebar
|
||||
export interface ArgumentConfig<Arguments = {}> {
|
||||
/** The name of the function argument configured by this argument form */
|
||||
name: keyof Arguments;
|
||||
/** The name to display */
|
||||
displayName: string;
|
||||
/** The argument type */
|
||||
argType: string;
|
||||
/** A description of the argument */
|
||||
help?: string;
|
||||
}
|
20
x-pack/legacy/plugins/canvas/types/transforms.ts
Normal file
20
x-pack/legacy/plugins/canvas/types/transforms.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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 { ArgumentConfig } from './arguments';
|
||||
|
||||
export interface TransformSpec<Arguments = {}> {
|
||||
/** The name of the function to create a transform section in the sidebar for */
|
||||
name: string;
|
||||
/** The name to display */
|
||||
displayName: string;
|
||||
/** A description of what is rendered */
|
||||
help?: string;
|
||||
/** A list of arguments to display in the */
|
||||
args: Array<ArgumentConfig<Arguments>>;
|
||||
}
|
||||
|
||||
export type TransformFactory<Arguments = {}> = () => TransformSpec<Arguments>;
|
Loading…
Add table
Add a link
Reference in a new issue