Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cases] Adding deprecated icon to additional actions dropdown selectors #115287

Merged
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
2c387e9
adding deprecated icon to the other actions list
jonathan-buttner Oct 15, 2021
b7ea813
Merge branch 'master' of github.com:elastic/kibana into connectors-de…
jonathan-buttner Oct 19, 2021
6c93aa5
Adding deprecated text to list view
jonathan-buttner Oct 20, 2021
9026520
Merge branch 'master' of github.com:elastic/kibana into connectors-de…
jonathan-buttner Oct 20, 2021
31ea456
Each action type can render the dropdown row
jonathan-buttner Oct 21, 2021
2acc4c6
Merge branch 'master' of github.com:elastic/kibana into connectors-de…
jonathan-buttner Oct 25, 2021
aa7b647
Refactoring and fixing todos
jonathan-buttner Oct 25, 2021
0403c15
Fixing jest tests
jonathan-buttner Oct 25, 2021
2cbbace
Adding and fixing other tests
jonathan-buttner Oct 25, 2021
6c71628
Fixing functional test
jonathan-buttner Oct 25, 2021
02a48f4
Merge branch 'master' of github.com:elastic/kibana into connectors-de…
jonathan-buttner Oct 26, 2021
1444fda
Merge branch 'master' into connectors-deprecated-icon
kibanamachine Oct 26, 2021
2d60ec6
Fixing tests
jonathan-buttner Oct 26, 2021
4e18f13
Merge branch 'connectors-deprecated-icon' of github.com:jonathan-butt…
jonathan-buttner Oct 26, 2021
58778e9
Merge branch 'master' into connectors-deprecated-icon
kibanamachine Oct 26, 2021
4186801
Merge branch 'master' into connectors-deprecated-icon
kibanamachine Oct 27, 2021
6abb14f
Merge branch 'master' into connectors-deprecated-icon
kibanamachine Oct 27, 2021
0e462f6
Adjusting text to match cases
jonathan-buttner Oct 27, 2021
bb4de03
Merge branch 'master' into connectors-deprecated-icon
kibanamachine Oct 28, 2021
6df58da
Merge branch 'main' of github.com:elastic/kibana into connectors-depr…
jonathan-buttner Nov 15, 2021
45079ef
Fixing tests
jonathan-buttner Nov 15, 2021
ae9a377
Merge branch 'main' of github.com:elastic/kibana into connectors-depr…
jonathan-buttner Nov 19, 2021
5ba6fa1
Addressing pr feedback
jonathan-buttner Nov 22, 2021
c8d88b3
Merge branch 'main' of github.com:elastic/kibana into connectors-depr…
jonathan-buttner Nov 22, 2021
1c706b8
Renaming connector dropdown to selection
jonathan-buttner Nov 22, 2021
fa0f045
Fixing type errors
jonathan-buttner Nov 22, 2021
3f02f8e
Fixing type error
jonathan-buttner Nov 22, 2021
fc8bb6d
Fixing translation error
jonathan-buttner Nov 22, 2021
b308867
Fixing test
jonathan-buttner Nov 23, 2021
4981da4
Merge branch 'main' into connectors-deprecated-icon
kibanamachine Nov 24, 2021
02bf882
Merge branch 'main' into connectors-deprecated-icon
kibanamachine Nov 29, 2021
09a028f
Merge branch 'main' of github.com:elastic/kibana into connectors-depr…
jonathan-buttner Dec 1, 2021
13536d4
Merge branch 'connectors-deprecated-icon' of github.com:jonathan-butt…
jonathan-buttner Dec 1, 2021
0ed891f
Addressing ux feedback and using ComboBox
jonathan-buttner Dec 2, 2021
10772b9
Merge branch 'main' of github.com:elastic/kibana into connectors-depr…
jonathan-buttner Dec 3, 2021
383d05c
Merge branch 'main' into connectors-deprecated-icon
kibanamachine Dec 6, 2021
09145c9
Extracting customConnectorSelectItem to an interface
jonathan-buttner Dec 7, 2021
115e917
Merge branch 'connectors-deprecated-icon' of github.com:jonathan-butt…
jonathan-buttner Dec 7, 2021
d96a447
Merge branch 'main' of github.com:elastic/kibana into connectors-depr…
jonathan-buttner Dec 7, 2021
51cb6dc
Merge branch 'main' into connectors-deprecated-icon
kibanamachine Dec 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion x-pack/plugins/translations/translations/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -25986,7 +25986,6 @@
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.deleteActionDisabledDescription": "コネクターを削除できません",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.deleteActionName": "削除",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.fixActionDescription": "コネクター構成を修正",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.isDeprecatedDescription": "このコネクターは廃止予定です。更新するか新しく作成してください。",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.missingSecretsDescription": "機密情報はインポートされませんでした",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.runConnectorDescription": "このコネクターを実行",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.runConnectorDisabledDescription": "コネクターを実行できません",
Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/translations/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -26434,7 +26434,6 @@
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.deleteActionDisabledDescription": "无法删除连接器",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.deleteActionName": "删除",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.fixActionDescription": "修复连接器配置",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.isDeprecatedDescription": "此连接器已过时。请进行更新,或创建新连接器。",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.missingSecretsDescription": "未导入敏感信息",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.runConnectorDescription": "运行此连接器",
"xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.runConnectorDisabledDescription": "无法运行连接器",
Expand Down
13 changes: 13 additions & 0 deletions x-pack/plugins/triggers_actions_ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,11 @@ Each action type should be defined as an `ActionTypeModel` object with the follo
validateParams: (actionParams: any) => Promise<ValidationResult>;
actionConnectorFields: React.FunctionComponent<any> | null;
actionParamsFields: React.LazyExoticComponent<ComponentType<ActionParamsProps<ActionParams>>>;
customConnectorSelectItem?: {
getText: (connector: ActionConnector) => string;
getComponent: (connector: ActionConnector) => React.
LazyExoticComponent<ComponentType<{ actionConnector: ActionConnector }> | undefined;
};
```
|Property|Description|
|---|---|
Expand All @@ -1127,6 +1132,14 @@ Each action type should be defined as an `ActionTypeModel` object with the follo
|validateParams|Validation function for action params.|
|actionConnectorFields|A lazy loaded React component for building UI of current action type connector.|
|actionParamsFields|A lazy loaded React component for building UI of current action type params. Displayed as a part of Create Alert flyout.|
|customConnectorSelectItem|Optional, an object for customizing the selection row of the action connector form.|

### customConnectorSelectItem Property

|Property|Description|
|---|---|
|getText|Function for returning the text to display for the row.|
|getComponent|Function for returning a lazy loaded React component for customizing the selection row of the action connector form. Or undefined if if no customization is needed.|

## Register action type model

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,21 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';

interface Props {
onMigrate: () => void;
onMigrate?: () => void;
}

const DeprecatedCalloutComponent: React.FC<Props> = ({ onMigrate }) => {
const update =
onMigrate != null ? (
<EuiLink onClick={onMigrate} data-test-subj="update-connector-btn">
{updateThisConnectorMessage}
</EuiLink>
) : (
<span>{updateThisConnectorMessage}</span>
);

return (
<>
<EuiSpacer size="s" />
<EuiCallOut
size="m"
iconType="alert"
Expand All @@ -34,16 +42,7 @@ const DeprecatedCalloutComponent: React.FC<Props> = ({ onMigrate }) => {
defaultMessage="{update} {create} "
id="xpack.triggersActionsUI.components.builtinActionTypes.servicenow.appInstallationInfo"
values={{
update: (
<EuiLink onClick={onMigrate} data-test-subj="update-connector-btn">
{i18n.translate(
'xpack.triggersActionsUI.components.builtinActionTypes.serviceNow.deprecatedCalloutMigrate',
{
defaultMessage: 'Update this connector,',
}
)}
</EuiLink>
),
update,
create: (
<span>
{i18n.translate(
Expand All @@ -63,3 +62,10 @@ const DeprecatedCalloutComponent: React.FC<Props> = ({ onMigrate }) => {
};

export const DeprecatedCallout = memo(DeprecatedCalloutComponent);

const updateThisConnectorMessage = i18n.translate(
'xpack.triggersActionsUI.components.builtinActionTypes.serviceNow.deprecatedCalloutMigrate',
{
defaultMessage: 'Update this connector,',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,26 @@
* 2.0.
*/

import { isRESTApiError, isFieldInvalid, isDeprecatedConnector } from './helpers';
import {
isRESTApiError,
isFieldInvalid,
getConnectorDescriptiveTitle,
getSelectedConnectorIcon,
} from './helpers';
import { ActionConnector } from '../../../../types';

const deprecatedConnector: ActionConnector = {
secrets: {},
config: {
usesTableApi: true,
},
id: 'test',
actionTypeId: '.servicenow',
name: 'Test',
isPreconfigured: false,
};

const validConnector = { ...deprecatedConnector, config: { usesTableApi: false } };

describe('helpers', () => {
describe('isRESTApiError', () => {
Expand Down Expand Up @@ -49,50 +68,23 @@ describe('helpers', () => {
});
});

describe('isDeprecatedConnector', () => {
const connector = {
id: 'test',
actionTypeId: '.webhook',
name: 'Test',
config: { apiUrl: 'http://example.com', usesTableApi: false },
secrets: { username: 'test', password: 'test' },
isPreconfigured: false as const,
};

it('returns false if the connector is not defined', () => {
expect(isDeprecatedConnector()).toBe(false);
describe('getConnectorDescriptiveTitle', () => {
it('adds deprecated to the connector name when the connector usesTableApi', () => {
expect(getConnectorDescriptiveTitle(deprecatedConnector)).toEqual('Test (deprecated)');
});

it('returns false if the connector is not ITSM or SecOps', () => {
expect(isDeprecatedConnector(connector)).toBe(false);
});

it('returns false if the connector is .servicenow and the usesTableApi=false', () => {
expect(isDeprecatedConnector({ ...connector, actionTypeId: '.servicenow' })).toBe(false);
});

it('returns false if the connector is .servicenow-sir and the usesTableApi=false', () => {
expect(isDeprecatedConnector({ ...connector, actionTypeId: '.servicenow-sir' })).toBe(false);
it('does not add deprecated when the connector has usesTableApi:false', () => {
expect(getConnectorDescriptiveTitle(validConnector)).toEqual('Test');
});
});

it('returns true if the connector is .servicenow and the usesTableApi=true', () => {
expect(
isDeprecatedConnector({
...connector,
actionTypeId: '.servicenow',
config: { ...connector.config, usesTableApi: true },
})
).toBe(true);
describe('getSelectedConnectorIcon', () => {
it('returns undefined when the connector has usesTableApi:false', () => {
expect(getSelectedConnectorIcon(validConnector)).toBeUndefined();
});

it('returns true if the connector is .servicenow-sir and the usesTableApi=true', () => {
expect(
isDeprecatedConnector({
...connector,
actionTypeId: '.servicenow-sir',
config: { ...connector.config, usesTableApi: true },
})
).toBe(true);
it('returns a component when the connector has usesTableApi:true', () => {
expect(getSelectedConnectorIcon(deprecatedConnector)).toBeDefined();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@
* 2.0.
*/

import { lazy, ComponentType } from 'react';
import { EuiSelectOption } from '@elastic/eui';
import { IErrorObject } from '../../../../../public/types';
import { AppInfo, Choice, RESTApiError, ServiceNowActionConnector } from './types';
import { AppInfo, Choice, RESTApiError } from './types';
import { ActionConnector, IErrorObject } from '../../../../types';
import {
deprecatedMessage,
checkConnectorIsDeprecated,
} from '../../../../common/connectors_selection';

export const DEFAULT_CORRELATION_ID = '{{rule.id}}:{{alert.id}}';

Expand All @@ -22,22 +27,20 @@ export const isFieldInvalid = (
error: string | IErrorObject | string[]
): boolean => error !== undefined && error.length > 0 && field != null;

// TODO: Remove when the applications are certified
export const isDeprecatedConnector = (connector?: ServiceNowActionConnector): boolean => {
if (connector == null) {
return false;
}
export const getConnectorDescriptiveTitle = (connector: ActionConnector) => {
let title = connector.name;

if (connector.actionTypeId === '.servicenow' || connector.actionTypeId === '.servicenow-sir') {
/**
* Connector's prior to the Elastic ServiceNow application
* use the Table API (https://developer.servicenow.com/dev.do#!/reference/api/rome/rest/c_TableAPI)
* Connectors after the Elastic ServiceNow application use the
* Import Set API (https://developer.servicenow.com/dev.do#!/reference/api/rome/rest/c_ImportSetAPI)
* A ServiceNow connector is considered deprecated if it uses the Table API.
*/
return !!connector.config.usesTableApi;
if (checkConnectorIsDeprecated(connector)) {
title += ` ${deprecatedMessage}`;
}

return false;
return title;
};

export const getSelectedConnectorIcon = (
actionConnector: ActionConnector
): React.LazyExoticComponent<ComponentType<{ actionConnector: ActionConnector }>> | undefined => {
if (checkConnectorIsDeprecated(actionConnector)) {
return lazy(() => import('./servicenow_selection_row'));
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
ServiceNowITOMActionParams,
} from './types';
import { isValidUrl } from '../../../lib/value_validators';
import { getConnectorDescriptiveTitle, getSelectedConnectorIcon } from './helpers';

const validateConnector = async (
action: ServiceNowActionConnector
Expand Down Expand Up @@ -138,6 +139,10 @@ export function getServiceNowITSMActionType(): ActionTypeModel<
return validationResult;
},
actionParamsFields: lazy(() => import('./servicenow_itsm_params')),
customConnectorSelectItem: {
getText: getConnectorDescriptiveTitle,
getComponent: getSelectedConnectorIcon,
},
};
}

Expand Down Expand Up @@ -174,6 +179,10 @@ export function getServiceNowSIRActionType(): ActionTypeModel<
return validationResult;
},
actionParamsFields: lazy(() => import('./servicenow_sir_params')),
customConnectorSelectItem: {
getText: getConnectorDescriptiveTitle,
getComponent: getSelectedConnectorIcon,
},
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import React, { useCallback, useEffect, useState } from 'react';

import { EuiSpacer } from '@elastic/eui';
import { ActionConnectorFieldsProps } from '../../../../types';

import * as i18n from './translations';
Expand All @@ -15,11 +16,16 @@ import { useKibana } from '../../../../common/lib/kibana';
import { DeprecatedCallout } from './deprecated_callout';
import { useGetAppInfo } from './use_get_app_info';
import { ApplicationRequiredCallout } from './application_required_callout';
import { isRESTApiError, isDeprecatedConnector } from './helpers';
import { isRESTApiError } from './helpers';
import { InstallationCallout } from './installation_callout';
import { UpdateConnector } from './update_connector';
import { updateActionConnector } from '../../../lib/action_connector_api';
import { Credentials } from './credentials';
import { checkConnectorIsDeprecated } from '../../../../common/connectors_selection';

// eslint-disable-next-line import/no-default-export
export { ServiceNowConnectorFields as default };

// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { snExternalServiceConfig } from '../../../../../../actions/server/builtin_action_types/servicenow/config';

Expand All @@ -40,7 +46,7 @@ const ServiceNowConnectorFields: React.FC<ActionConnectorFieldsProps<ServiceNowA
} = useKibana().services;
const { apiUrl, usesTableApi } = action.config;
const { username, password } = action.secrets;
const requiresNewApplication = !isDeprecatedConnector(action);
const requiresNewApplication = !checkConnectorIsDeprecated(action);

const [showUpdateConnector, setShowUpdateConnector] = useState(false);

Expand Down Expand Up @@ -156,7 +162,7 @@ const ServiceNowConnectorFields: React.FC<ActionConnectorFieldsProps<ServiceNowA
{requiresNewApplication && (
<InstallationCallout appId={snExternalServiceConfig[action.actionTypeId].appId ?? ''} />
)}
{!requiresNewApplication && <DeprecatedCallout onMigrate={onMigrateClick} />}
{!requiresNewApplication && <SpacedDeprecatedCallout onMigrate={onMigrateClick} />}
<Credentials
action={action}
errors={errors}
Expand All @@ -175,5 +181,9 @@ const ServiceNowConnectorFields: React.FC<ActionConnectorFieldsProps<ServiceNowA
);
};

// eslint-disable-next-line import/no-default-export
export { ServiceNowConnectorFields as default };
const SpacedDeprecatedCallout = ({ onMigrate }: { onMigrate: () => void }) => (
<>
<EuiSpacer size="s" />
<DeprecatedCallout onMigrate={onMigrate} />
</>
);
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ import { FormattedMessage } from '@kbn/i18n-react';

import { useKibana } from '../../../../common/lib/kibana';
import { ActionParamsProps } from '../../../../types';
import { ServiceNowITSMActionParams, Choice, Fields, ServiceNowActionConnector } from './types';
import { ServiceNowITSMActionParams, Choice, Fields } from './types';
import { TextAreaWithMessageVariables } from '../../text_area_with_message_variables';
import { TextFieldWithMessageVariables } from '../../text_field_with_message_variables';
import { useGetChoices } from './use_get_choices';
import { choicesToEuiOptions, DEFAULT_CORRELATION_ID, isDeprecatedConnector } from './helpers';
import { choicesToEuiOptions, DEFAULT_CORRELATION_ID } from './helpers';

import * as i18n from './translations';
import { checkConnectorIsDeprecated } from '../../../../common/connectors_selection';

const useGetChoicesFields = ['urgency', 'severity', 'impact', 'category', 'subcategory'];
const defaultFields: Fields = {
Expand All @@ -46,6 +47,8 @@ const ServiceNowParamsFields: React.FunctionComponent<
notifications: { toasts },
} = useKibana().services;

const isDeprecatedActionConnector = checkConnectorIsDeprecated(actionConnector);

const actionConnectorRef = useRef(actionConnector?.id ?? '');
const { incident, comments } = useMemo(
() =>
Expand Down Expand Up @@ -238,7 +241,7 @@ const ServiceNowParamsFields: React.FunctionComponent<
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
{!isDeprecatedConnector(actionConnector as unknown as ServiceNowActionConnector) && (
{!isDeprecatedActionConnector && (
<>
<EuiFlexGroup>
<EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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 { EuiIconTip } from '@elastic/eui';
import React from 'react';
import { i18n } from '@kbn/i18n';

import { ActionConnector } from '../../../../types';
import { connectorDeprecatedMessage } from '../../../../common/connectors_selection';

// eslint-disable-next-line import/no-default-export
export { ServiceNowSelectableRowIcon as default };

export function ServiceNowSelectableRowIcon({
actionConnector,
}: {
actionConnector: ActionConnector;
}) {
return (
<EuiIconTip
aria-label={deprecatedTooltipTitle}
type="alert"
color="warning"
content={connectorDeprecatedMessage}
data-test-subj={`deprecated-connector-icon-${actionConnector.id}`}
anchorClassName={'euiFormControlLayout__prepend'}
/>
);
}

const deprecatedTooltipTitle = i18n.translate(
'xpack.triggersActionsUI.sections.actionForm.deprecatedTooltipTitle',
{
defaultMessage: 'Deprecated connector',
}
);
Loading