From 14fa82dc54a3bd96ef68767f78cb8b6a8367fbae Mon Sep 17 00:00:00 2001 From: Patrick Mueller Date: Mon, 25 Jan 2021 16:43:46 -0500 Subject: [PATCH] [alerts] adds support for index threshold index param string type (#88540) resolves https://github.com/elastic/kibana/issues/68575 The index threshold alert defines an `index` parameter which is typed as `string | string[]`. However the UI for this alert has been typing it as only `string[]`. This PR changes the UI to work with an incoming string value for this parameter. If the parameter is edited in the UI, it will always be set as an array, even if there is only one element. --- .../alert_types/threshold/expression.tsx | 21 ++++++++++++------- .../public/alert_types/threshold/types.ts | 2 +- .../alert_types/threshold/validation.test.ts | 2 +- .../apps/triggers_actions_ui/details.ts | 2 +- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.tsx b/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.tsx index 35b62d1f73f2..8348a797972a 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.tsx @@ -75,6 +75,12 @@ function isString(value: unknown): value is string { return typeof value === 'string'; } +// normalize the `index` parameter to be a string array +function indexParamToArray(index: string | string[]): string[] { + if (!index) return []; + return isString(index) ? [index] : index; +} + export const IndexThresholdAlertTypeExpression: React.FunctionComponent< AlertTypeParamsExpressionProps > = ({ alertParams, alertInterval, setAlertParams, setAlertProperty, errors, charts, data }) => { @@ -92,6 +98,7 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent< timeWindowUnit, } = alertParams; + const indexArray = indexParamToArray(index); const { http } = useKibana().services; const [indexPopoverOpen, setIndexPopoverOpen] = useState(false); @@ -131,8 +138,8 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent< threshold: threshold ?? DEFAULT_VALUES.THRESHOLD, }); - if (index && index.length > 0) { - const currentEsFields = await getFields(http, index); + if (indexArray.length > 0) { + const currentEsFields = await getFields(http, indexArray); const timeFields = getTimeFieldOptions(currentEsFields); setEsFields(currentEsFields); @@ -170,7 +177,7 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent< defaultMessage="Indices to query" /> } - isInvalid={errors.index.length > 0 && index !== undefined} + isInvalid={errors.index.length > 0 && indexArray.length > 0} error={errors.index} helpText={ 0 && index !== undefined} + isInvalid={errors.index.length > 0 && indexArray.length > 0} noSuggestions={!indexOptions.length} options={indexOptions} data-test-subj="thresholdIndexesComboBox" - selectedOptions={(index || []).map((anIndex: string) => { + selectedOptions={indexArray.map((anIndex: string) => { return { label: anIndex, value: anIndex, @@ -306,12 +313,12 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent< description={i18n.translate('xpack.stackAlerts.threshold.ui.alertParams.indexLabel', { defaultMessage: 'index', })} - value={index && index.length > 0 ? renderIndices(index) : firstFieldOption.text} + value={indexArray.length > 0 ? renderIndices(indexArray) : firstFieldOption.text} isActive={indexPopoverOpen} onClick={() => { setIndexPopoverOpen(true); }} - isInvalid={!(index && index.length > 0 && timeField !== '')} + isInvalid={!(indexArray.length > 0 && timeField !== '')} /> } isOpen={indexPopoverOpen} diff --git a/x-pack/plugins/stack_alerts/public/alert_types/threshold/types.ts b/x-pack/plugins/stack_alerts/public/alert_types/threshold/types.ts index 4868b92feaeb..32460c19ebdf 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/threshold/types.ts +++ b/x-pack/plugins/stack_alerts/public/alert_types/threshold/types.ts @@ -27,7 +27,7 @@ export interface GroupByType { } export interface IndexThresholdAlertParams extends AlertTypeParams { - index: string[]; + index: string | string[]; timeField?: string; aggType: string; aggField?: string; diff --git a/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.test.ts b/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.test.ts index 1f24a094d0ec..d8f2d24b106f 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.test.ts +++ b/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.test.ts @@ -32,7 +32,7 @@ describe('expression params validation', () => { }); test('if aggField property is invalid should return proper error message', () => { const initialParams: IndexThresholdAlertParams = { - index: ['test'], + index: 'test', aggType: 'avg', threshold: [], timeWindowSize: 1, diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts index 1ed0b38a238b..35e2e0396902 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts @@ -228,7 +228,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { timeWindowUnit: 'm', groupBy: 'all', threshold: [1000, 5000], - index: ['.kibana_1'], + index: '.kibana_1', timeField: 'alert', }, actions: [