mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Added support for docLinks plugin in Connectors forms and missing save capabilities for modal dialog (#64986) (#65289)
* Added support for docLinks plugin in Connectors forms and missing save capabilities for modal dialog * Fixed tests * Extended alert context with application capabilities * Fixed due to comments * Fixed typecheck Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> # Conflicts: # x-pack/plugins/infra/public/components/alerting/inventory/alert_flyout.tsx # x-pack/plugins/triggers_actions_ui/public/application/context/alerts_context.tsx
This commit is contained in:
parent
7cb65c5548
commit
55de3186f8
36 changed files with 397 additions and 141 deletions
|
@ -27,6 +27,7 @@ import {
|
|||
IUiSettingsClient,
|
||||
DocLinksStart,
|
||||
ToastsSetup,
|
||||
ApplicationStart,
|
||||
} from '../../../src/core/public';
|
||||
import { DataPublicPluginStart } from '../../../src/plugins/data/public';
|
||||
import { ChartsPluginStart } from '../../../src/plugins/charts/public';
|
||||
|
@ -48,6 +49,7 @@ export interface AlertingExampleComponentParams {
|
|||
uiSettings: IUiSettingsClient;
|
||||
docLinks: DocLinksStart;
|
||||
toastNotifications: ToastsSetup;
|
||||
capabilities: ApplicationStart['capabilities'];
|
||||
}
|
||||
|
||||
const AlertingExampleApp = (deps: AlertingExampleComponentParams) => {
|
||||
|
@ -102,6 +104,7 @@ export const renderApp = (
|
|||
http={http}
|
||||
uiSettings={uiSettings}
|
||||
docLinks={docLinks}
|
||||
capabilities={application.capabilities}
|
||||
{...deps}
|
||||
/>,
|
||||
element
|
||||
|
|
|
@ -36,6 +36,7 @@ export const CreateAlert = ({
|
|||
docLinks,
|
||||
data,
|
||||
toastNotifications,
|
||||
capabilities,
|
||||
}: AlertingExampleComponentParams) => {
|
||||
const [alertFlyoutVisible, setAlertFlyoutVisibility] = useState<boolean>(false);
|
||||
|
||||
|
@ -60,6 +61,7 @@ export const CreateAlert = ({
|
|||
docLinks,
|
||||
charts,
|
||||
dataFieldsFormats: data.fieldFormats,
|
||||
capabilities,
|
||||
}}
|
||||
>
|
||||
<AlertAdd
|
||||
|
|
|
@ -74,6 +74,7 @@ const ApmAppRoot = ({
|
|||
value={{
|
||||
http: core.http,
|
||||
docLinks: core.docLinks,
|
||||
capabilities: core.application.capabilities,
|
||||
toastNotifications: core.notifications.toasts,
|
||||
actionTypeRegistry: plugins.triggers_actions_ui.actionTypeRegistry,
|
||||
alertTypeRegistry: plugins.triggers_actions_ui.alertTypeRegistry
|
||||
|
|
|
@ -36,6 +36,7 @@ export const AlertFlyout = (props: Props) => {
|
|||
toastNotifications: services.notifications?.toasts,
|
||||
http: services.http,
|
||||
docLinks: services.docLinks,
|
||||
capabilities: services.application.capabilities,
|
||||
actionTypeRegistry: triggersActionsUI.actionTypeRegistry,
|
||||
alertTypeRegistry: triggersActionsUI.alertTypeRegistry,
|
||||
}}
|
||||
|
|
|
@ -30,6 +30,7 @@ export const AlertFlyout = (props: Props) => {
|
|||
toastNotifications: services.notifications?.toasts,
|
||||
http: services.http,
|
||||
docLinks: services.docLinks,
|
||||
capabilities: services.application.capabilities,
|
||||
actionTypeRegistry: triggersActionsUI.actionTypeRegistry,
|
||||
alertTypeRegistry: triggersActionsUI.alertTypeRegistry,
|
||||
}}
|
||||
|
|
|
@ -64,7 +64,7 @@ interface ConfigureCasesComponentProps {
|
|||
|
||||
const ConfigureCasesComponent: React.FC<ConfigureCasesComponentProps> = ({ userCanCrud }) => {
|
||||
const search = useGetUrlSearch(navTabs.case);
|
||||
const { http, triggers_actions_ui, notifications, application } = useKibana().services;
|
||||
const { http, triggers_actions_ui, notifications, application, docLinks } = useKibana().services;
|
||||
|
||||
const [connectorIsValid, setConnectorIsValid] = useState(true);
|
||||
const [addFlyoutVisible, setAddFlyoutVisibility] = useState<boolean>(false);
|
||||
|
@ -291,6 +291,7 @@ const ConfigureCasesComponent: React.FC<ConfigureCasesComponentProps> = ({ userC
|
|||
toastNotifications: notifications.toasts,
|
||||
capabilities: application.capabilities,
|
||||
reloadConnectors,
|
||||
docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorAddFlyout
|
||||
|
|
|
@ -19,6 +19,15 @@ describe('RuleActionsField', () => {
|
|||
triggers_actions_ui: {
|
||||
actionTypeRegistry: {},
|
||||
},
|
||||
application: {
|
||||
capabilities: {
|
||||
actions: {
|
||||
delete: true,
|
||||
save: true,
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const Component = () => {
|
||||
|
|
|
@ -27,6 +27,8 @@ export const RuleActionsField: ThrottleSelectField = ({ field, messageVariables
|
|||
http,
|
||||
triggers_actions_ui: { actionTypeRegistry },
|
||||
notifications,
|
||||
docLinks,
|
||||
application: { capabilities },
|
||||
} = useKibana().services;
|
||||
|
||||
const setActionIdByIndex = useCallback(
|
||||
|
@ -78,6 +80,8 @@ export const RuleActionsField: ThrottleSelectField = ({ field, messageVariables
|
|||
actionTypes={supportedActionTypes}
|
||||
defaultActionMessage={DEFAULT_ACTION_MESSAGE}
|
||||
toastNotifications={notifications.toasts}
|
||||
docLinks={docLinks}
|
||||
capabilities={capabilities}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1374,7 +1374,7 @@ import { ActionsConnectorsContextProvider, ConnectorAddFlyout } from '../../../.
|
|||
const [addFlyoutVisible, setAddFlyoutVisibility] = useState<boolean>(false);
|
||||
|
||||
// load required dependancied
|
||||
const { http, triggers_actions_ui, toastNotifications, capabilities } = useKibana().services;
|
||||
const { http, triggers_actions_ui, toastNotifications, capabilities, docLinks } = useKibana().services;
|
||||
|
||||
const connector = {
|
||||
secrets: {},
|
||||
|
@ -1406,6 +1406,7 @@ const connector = {
|
|||
toastNotifications: toastNotifications,
|
||||
actionTypeRegistry: triggers_actions_ui.actionTypeRegistry,
|
||||
capabilities: capabilities,
|
||||
docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorAddFlyout
|
||||
|
@ -1447,6 +1448,7 @@ export interface ActionsConnectorsContextValue {
|
|||
'get$' | 'add' | 'remove' | 'addSuccess' | 'addWarning' | 'addDanger' | 'addError'
|
||||
>;
|
||||
capabilities: ApplicationStart['capabilities'];
|
||||
docLinks: DocLinksStart;
|
||||
reloadConnectors?: () => Promise<void>;
|
||||
}
|
||||
```
|
||||
|
|
|
@ -11,6 +11,7 @@ import { registerBuiltInActionTypes } from './index';
|
|||
import { ActionTypeModel, ActionParamsProps } from '../../../types';
|
||||
import { IndexActionParams, EsIndexActionConnector } from './types';
|
||||
import { coreMock } from '../../../../../../../src/core/public/mocks';
|
||||
import { ActionsConnectorsContextProvider } from '../../context/actions_connectors_context';
|
||||
jest.mock('../../../common/index_controls', () => ({
|
||||
firstFieldOption: jest.fn(),
|
||||
getFields: jest.fn(),
|
||||
|
@ -20,14 +21,35 @@ jest.mock('../../../common/index_controls', () => ({
|
|||
|
||||
const ACTION_TYPE_ID = '.index';
|
||||
let actionTypeModel: ActionTypeModel;
|
||||
let deps: any;
|
||||
|
||||
beforeAll(() => {
|
||||
beforeAll(async () => {
|
||||
const actionTypeRegistry = new TypeRegistry<ActionTypeModel>();
|
||||
registerBuiltInActionTypes({ actionTypeRegistry });
|
||||
const getResult = actionTypeRegistry.get(ACTION_TYPE_ID);
|
||||
if (getResult !== null) {
|
||||
actionTypeModel = getResult;
|
||||
}
|
||||
const mocks = coreMock.createSetup();
|
||||
const [
|
||||
{
|
||||
application: { capabilities },
|
||||
},
|
||||
] = await mocks.getStartServices();
|
||||
deps = {
|
||||
toastNotifications: mocks.notifications.toasts,
|
||||
http: mocks.http,
|
||||
capabilities: {
|
||||
...capabilities,
|
||||
actions: {
|
||||
delete: true,
|
||||
save: true,
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
};
|
||||
});
|
||||
|
||||
describe('actionTypeRegistry.get() works', () => {
|
||||
|
@ -99,8 +121,6 @@ describe('action params validation', () => {
|
|||
|
||||
describe('IndexActionConnectorFields renders', () => {
|
||||
test('all connector fields is rendered', async () => {
|
||||
const mocks = coreMock.createSetup();
|
||||
|
||||
expect(actionTypeModel.actionConnectorFields).not.toBeNull();
|
||||
if (!actionTypeModel.actionConnectorFields) {
|
||||
return;
|
||||
|
@ -145,13 +165,25 @@ describe('IndexActionConnectorFields renders', () => {
|
|||
},
|
||||
} as EsIndexActionConnector;
|
||||
const wrapper = mountWithIntl(
|
||||
<ConnectorFields
|
||||
action={actionConnector}
|
||||
errors={{ index: [] }}
|
||||
editActionConfig={() => {}}
|
||||
editActionSecrets={() => {}}
|
||||
http={mocks.http}
|
||||
/>
|
||||
<ActionsConnectorsContextProvider
|
||||
value={{
|
||||
http: deps!.http,
|
||||
actionTypeRegistry: deps!.actionTypeRegistry,
|
||||
capabilities: deps!.capabilities,
|
||||
toastNotifications: deps!.toastNotifications,
|
||||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps!.docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorFields
|
||||
action={actionConnector}
|
||||
errors={{ index: [] }}
|
||||
editActionConfig={() => {}}
|
||||
editActionSecrets={() => {}}
|
||||
/>
|
||||
</ActionsConnectorsContextProvider>
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
|
|
|
@ -33,6 +33,7 @@ import {
|
|||
getIndexPatterns,
|
||||
} from '../../../common/index_controls';
|
||||
import { AddMessageVariables } from '../add_message_variables';
|
||||
import { useActionsConnectorsContext } from '../../context/actions_connectors_context';
|
||||
|
||||
export function getActionType(): ActionTypeModel {
|
||||
return {
|
||||
|
@ -78,7 +79,8 @@ export function getActionType(): ActionTypeModel {
|
|||
|
||||
const IndexActionConnectorFields: React.FunctionComponent<ActionConnectorFieldsProps<
|
||||
EsIndexActionConnector
|
||||
>> = ({ action, editActionConfig, errors, http }) => {
|
||||
>> = ({ action, editActionConfig, errors }) => {
|
||||
const { http } = useActionsConnectorsContext();
|
||||
const { index, refresh, executionTimeField } = action.config;
|
||||
const [hasTimeFieldCheckbox, setTimeFieldCheckboxState] = useState<boolean>(
|
||||
executionTimeField != null
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import { mountWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { coreMock } from '../../../../../../../src/core/public/mocks';
|
||||
import { TypeRegistry } from '../../type_registry';
|
||||
import { registerBuiltInActionTypes } from './index';
|
||||
import { ActionTypeModel, ActionParamsProps } from '../../../types';
|
||||
|
@ -14,17 +16,39 @@ import {
|
|||
SeverityActionOptions,
|
||||
PagerDutyActionConnector,
|
||||
} from './types';
|
||||
import { ActionsConnectorsContextProvider } from '../../context/actions_connectors_context';
|
||||
|
||||
const ACTION_TYPE_ID = '.pagerduty';
|
||||
let actionTypeModel: ActionTypeModel;
|
||||
let deps: any;
|
||||
|
||||
beforeAll(() => {
|
||||
beforeAll(async () => {
|
||||
const actionTypeRegistry = new TypeRegistry<ActionTypeModel>();
|
||||
registerBuiltInActionTypes({ actionTypeRegistry });
|
||||
const getResult = actionTypeRegistry.get(ACTION_TYPE_ID);
|
||||
if (getResult !== null) {
|
||||
actionTypeModel = getResult;
|
||||
}
|
||||
const mocks = coreMock.createSetup();
|
||||
const [
|
||||
{
|
||||
application: { capabilities },
|
||||
},
|
||||
] = await mocks.getStartServices();
|
||||
deps = {
|
||||
toastNotifications: mocks.notifications.toasts,
|
||||
http: mocks.http,
|
||||
capabilities: {
|
||||
...capabilities,
|
||||
actions: {
|
||||
delete: true,
|
||||
save: true,
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
};
|
||||
});
|
||||
|
||||
describe('actionTypeRegistry.get() works', () => {
|
||||
|
@ -106,7 +130,7 @@ describe('pagerduty action params validation', () => {
|
|||
});
|
||||
|
||||
describe('PagerDutyActionConnectorFields renders', () => {
|
||||
test('all connector fields is rendered', () => {
|
||||
test('all connector fields is rendered', async () => {
|
||||
expect(actionTypeModel.actionConnectorFields).not.toBeNull();
|
||||
if (!actionTypeModel.actionConnectorFields) {
|
||||
return;
|
||||
|
@ -124,13 +148,31 @@ describe('PagerDutyActionConnectorFields renders', () => {
|
|||
},
|
||||
} as PagerDutyActionConnector;
|
||||
const wrapper = mountWithIntl(
|
||||
<ConnectorFields
|
||||
action={actionConnector}
|
||||
errors={{ routingKey: [] }}
|
||||
editActionConfig={() => {}}
|
||||
editActionSecrets={() => {}}
|
||||
/>
|
||||
<ActionsConnectorsContextProvider
|
||||
value={{
|
||||
http: deps!.http,
|
||||
actionTypeRegistry: deps!.actionTypeRegistry,
|
||||
capabilities: deps!.capabilities,
|
||||
toastNotifications: deps!.toastNotifications,
|
||||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps!.docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorFields
|
||||
action={actionConnector}
|
||||
errors={{ index: [], routingKey: [] }}
|
||||
editActionConfig={() => {}}
|
||||
editActionSecrets={() => {}}
|
||||
/>
|
||||
</ActionsConnectorsContextProvider>
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await nextTick();
|
||||
wrapper.update();
|
||||
});
|
||||
expect(wrapper.find('[data-test-subj="pagerdutyApiUrlInput"]').length > 0).toBeTruthy();
|
||||
expect(
|
||||
wrapper
|
||||
|
|
|
@ -25,6 +25,7 @@ import { PagerDutyActionParams, PagerDutyActionConnector } from './types';
|
|||
import pagerDutySvg from './pagerduty.svg';
|
||||
import { AddMessageVariables } from '../add_message_variables';
|
||||
import { hasMustacheTokens } from '../../lib/has_mustache_tokens';
|
||||
import { useActionsConnectorsContext } from '../../context/actions_connectors_context';
|
||||
|
||||
export function getActionType(): ActionTypeModel {
|
||||
return {
|
||||
|
@ -105,6 +106,7 @@ export function getActionType(): ActionTypeModel {
|
|||
const PagerDutyActionConnectorFields: React.FunctionComponent<ActionConnectorFieldsProps<
|
||||
PagerDutyActionConnector
|
||||
>> = ({ errors, action, editActionConfig, editActionSecrets }) => {
|
||||
const { docLinks } = useActionsConnectorsContext();
|
||||
const { apiUrl } = action.config;
|
||||
const { routingKey } = action.secrets;
|
||||
return (
|
||||
|
@ -139,7 +141,7 @@ const PagerDutyActionConnectorFields: React.FunctionComponent<ActionConnectorFie
|
|||
fullWidth
|
||||
helpText={
|
||||
<EuiLink
|
||||
href="https://www.elastic.co/guide/en/kibana/current/pagerduty-action-type.html"
|
||||
href={`${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/pagerduty-action-type.html`}
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -4,22 +4,47 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import { mountWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { coreMock } from '../../../../../../../src/core/public/mocks';
|
||||
import { TypeRegistry } from '../../type_registry';
|
||||
import { registerBuiltInActionTypes } from './index';
|
||||
import { ActionTypeModel, ActionParamsProps } from '../../../types';
|
||||
import { SlackActionParams, SlackActionConnector } from './types';
|
||||
import { ActionsConnectorsContextProvider } from '../../context/actions_connectors_context';
|
||||
|
||||
const ACTION_TYPE_ID = '.slack';
|
||||
let actionTypeModel: ActionTypeModel;
|
||||
|
||||
beforeAll(() => {
|
||||
let deps: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const actionTypeRegistry = new TypeRegistry<ActionTypeModel>();
|
||||
registerBuiltInActionTypes({ actionTypeRegistry });
|
||||
const getResult = actionTypeRegistry.get(ACTION_TYPE_ID);
|
||||
if (getResult !== null) {
|
||||
actionTypeModel = getResult;
|
||||
}
|
||||
const mocks = coreMock.createSetup();
|
||||
const [
|
||||
{
|
||||
application: { capabilities },
|
||||
},
|
||||
] = await mocks.getStartServices();
|
||||
deps = {
|
||||
toastNotifications: mocks.notifications.toasts,
|
||||
http: mocks.http,
|
||||
capabilities: {
|
||||
...capabilities,
|
||||
actions: {
|
||||
delete: true,
|
||||
save: true,
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
};
|
||||
});
|
||||
|
||||
describe('actionTypeRegistry.get() works', () => {
|
||||
|
@ -78,7 +103,7 @@ describe('slack action params validation', () => {
|
|||
});
|
||||
|
||||
describe('SlackActionFields renders', () => {
|
||||
test('all connector fields is rendered', () => {
|
||||
test('all connector fields is rendered', async () => {
|
||||
expect(actionTypeModel.actionConnectorFields).not.toBeNull();
|
||||
if (!actionTypeModel.actionConnectorFields) {
|
||||
return;
|
||||
|
@ -94,13 +119,31 @@ describe('SlackActionFields renders', () => {
|
|||
config: {},
|
||||
} as SlackActionConnector;
|
||||
const wrapper = mountWithIntl(
|
||||
<ConnectorFields
|
||||
action={actionConnector}
|
||||
errors={{ webhookUrl: [] }}
|
||||
editActionConfig={() => {}}
|
||||
editActionSecrets={() => {}}
|
||||
/>
|
||||
<ActionsConnectorsContextProvider
|
||||
value={{
|
||||
http: deps!.http,
|
||||
actionTypeRegistry: deps!.actionTypeRegistry,
|
||||
capabilities: deps!.capabilities,
|
||||
toastNotifications: deps!.toastNotifications,
|
||||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps!.docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorFields
|
||||
action={actionConnector}
|
||||
errors={{ index: [], webhookUrl: [] }}
|
||||
editActionConfig={() => {}}
|
||||
editActionSecrets={() => {}}
|
||||
/>
|
||||
</ActionsConnectorsContextProvider>
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await nextTick();
|
||||
wrapper.update();
|
||||
});
|
||||
expect(wrapper.find('[data-test-subj="slackWebhookUrlInput"]').length > 0).toBeTruthy();
|
||||
expect(
|
||||
wrapper
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from '../../../types';
|
||||
import { SlackActionParams, SlackActionConnector } from './types';
|
||||
import { AddMessageVariables } from '../add_message_variables';
|
||||
import { useActionsConnectorsContext } from '../../context/actions_connectors_context';
|
||||
|
||||
export function getActionType(): ActionTypeModel {
|
||||
return {
|
||||
|
@ -76,6 +77,7 @@ export function getActionType(): ActionTypeModel {
|
|||
const SlackActionFields: React.FunctionComponent<ActionConnectorFieldsProps<
|
||||
SlackActionConnector
|
||||
>> = ({ action, editActionSecrets, errors }) => {
|
||||
const { docLinks } = useActionsConnectorsContext();
|
||||
const { webhookUrl } = action.secrets;
|
||||
|
||||
return (
|
||||
|
@ -85,7 +87,7 @@ const SlackActionFields: React.FunctionComponent<ActionConnectorFieldsProps<
|
|||
fullWidth
|
||||
helpText={
|
||||
<EuiLink
|
||||
href="https://www.elastic.co/guide/en/elasticsearch/reference/current/actions-slack.html#configuring-slack"
|
||||
href={`${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/slack-action-type.html`}
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import { HttpSetup, ToastsApi, ApplicationStart } from 'kibana/public';
|
||||
import { HttpSetup, ToastsApi, ApplicationStart, DocLinksStart } from 'kibana/public';
|
||||
import { ActionTypeModel } from '../../types';
|
||||
import { TypeRegistry } from '../type_registry';
|
||||
|
||||
|
@ -18,6 +18,7 @@ export interface ActionsConnectorsContextValue {
|
|||
>;
|
||||
capabilities: ApplicationStart['capabilities'];
|
||||
reloadConnectors?: () => Promise<void>;
|
||||
docLinks: DocLinksStart;
|
||||
}
|
||||
|
||||
const ActionsConnectorsContext = createContext<ActionsConnectorsContextValue>(null as any);
|
||||
|
|
|
@ -5,7 +5,13 @@
|
|||
*/
|
||||
|
||||
import React, { useContext, createContext } from 'react';
|
||||
import { HttpSetup, IUiSettingsClient, ToastsApi, DocLinksStart } from 'kibana/public';
|
||||
import {
|
||||
HttpSetup,
|
||||
IUiSettingsClient,
|
||||
ToastsApi,
|
||||
DocLinksStart,
|
||||
ApplicationStart,
|
||||
} from 'kibana/public';
|
||||
import { ChartsPluginSetup } from 'src/plugins/charts/public';
|
||||
import { FieldFormatsRegistry } from 'src/plugins/data/common/field_formats';
|
||||
import { TypeRegistry } from '../type_registry';
|
||||
|
@ -24,6 +30,7 @@ export interface AlertsContextValue<MetaData = Record<string, any>> {
|
|||
charts?: ChartsPluginSetup;
|
||||
dataFieldsFormats?: Pick<FieldFormatsRegistry, 'register'>;
|
||||
docLinks: DocLinksStart;
|
||||
capabilities: ApplicationStart['capabilities'];
|
||||
metadata?: MetaData;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,11 @@ import { coreMock } from '../../../../../../../src/core/public/mocks';
|
|||
import { actionTypeRegistryMock } from '../../action_type_registry.mock';
|
||||
import { ValidationResult, ActionConnector } from '../../../types';
|
||||
import { ActionConnectorForm } from './action_connector_form';
|
||||
import { ActionsConnectorsContextValue } from '../../context/actions_connectors_context';
|
||||
import { ActionsConnectorsContextProvider } from '../../context/actions_connectors_context';
|
||||
const actionTypeRegistry = actionTypeRegistryMock.create();
|
||||
|
||||
describe('action_connector_form', () => {
|
||||
let deps: ActionsConnectorsContextValue;
|
||||
let deps: any;
|
||||
beforeAll(async () => {
|
||||
const mocks = coreMock.createSetup();
|
||||
const [
|
||||
|
@ -33,6 +33,7 @@ describe('action_connector_form', () => {
|
|||
},
|
||||
},
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -62,14 +63,25 @@ describe('action_connector_form', () => {
|
|||
let wrapper;
|
||||
if (deps) {
|
||||
wrapper = mountWithIntl(
|
||||
<ActionConnectorForm
|
||||
actionTypeName={'my-action-type-name'}
|
||||
connector={initialConnector}
|
||||
dispatch={() => {}}
|
||||
errors={{ name: [] }}
|
||||
actionTypeRegistry={deps.actionTypeRegistry}
|
||||
http={deps.http}
|
||||
/>
|
||||
<ActionsConnectorsContextProvider
|
||||
value={{
|
||||
http: deps!.http,
|
||||
actionTypeRegistry: deps!.actionTypeRegistry,
|
||||
capabilities: deps!.capabilities,
|
||||
toastNotifications: deps!.toastNotifications,
|
||||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps!.docLinks,
|
||||
}}
|
||||
>
|
||||
<ActionConnectorForm
|
||||
actionTypeName={'my-action-type-name'}
|
||||
connector={initialConnector}
|
||||
dispatch={() => {}}
|
||||
errors={{ name: [] }}
|
||||
/>
|
||||
</ActionsConnectorsContextProvider>
|
||||
);
|
||||
}
|
||||
const connectorNameField = wrapper?.find('[data-test-subj="nameInput"]');
|
||||
|
|
|
@ -15,10 +15,9 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { HttpSetup } from 'kibana/public';
|
||||
import { ReducerAction } from './connector_reducer';
|
||||
import { ActionConnector, IErrorObject, ActionTypeModel } from '../../../types';
|
||||
import { TypeRegistry } from '../../type_registry';
|
||||
import { ActionConnector, IErrorObject } from '../../../types';
|
||||
import { useActionsConnectorsContext } from '../../context/actions_connectors_context';
|
||||
|
||||
export function validateBaseProperties(actionObject: ActionConnector) {
|
||||
const validationResult = { errors: {} };
|
||||
|
@ -47,8 +46,6 @@ interface ActionConnectorProps {
|
|||
body: { message: string; error: string };
|
||||
};
|
||||
errors: IErrorObject;
|
||||
actionTypeRegistry: TypeRegistry<ActionTypeModel>;
|
||||
http: HttpSetup;
|
||||
}
|
||||
|
||||
export const ActionConnectorForm = ({
|
||||
|
@ -57,9 +54,8 @@ export const ActionConnectorForm = ({
|
|||
actionTypeName,
|
||||
serverError,
|
||||
errors,
|
||||
actionTypeRegistry,
|
||||
http,
|
||||
}: ActionConnectorProps) => {
|
||||
const { actionTypeRegistry, docLinks } = useActionsConnectorsContext();
|
||||
const setActionProperty = (key: string, value: any) => {
|
||||
dispatch({ command: { type: 'setProperty' }, payload: { key, value } });
|
||||
};
|
||||
|
@ -94,7 +90,10 @@ export const ActionConnectorForm = ({
|
|||
values={{
|
||||
actionType: actionTypeName,
|
||||
docLink: (
|
||||
<EuiLink target="_blank">
|
||||
<EuiLink
|
||||
href={`${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/action-types.html`}
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.actionConnectorForm.actions.actionConfigurationWarningHelpLinkText"
|
||||
defaultMessage="Learn more."
|
||||
|
@ -151,7 +150,6 @@ export const ActionConnectorForm = ({
|
|||
errors={errors}
|
||||
editActionConfig={setActionConfigProperty}
|
||||
editActionSecrets={setActionSecretsProperty}
|
||||
http={http}
|
||||
/>
|
||||
) : null}
|
||||
</EuiForm>
|
||||
|
|
|
@ -127,11 +127,25 @@ describe('action_form', () => {
|
|||
isPreconfigured: false,
|
||||
},
|
||||
]);
|
||||
const mockes = coreMock.createSetup();
|
||||
const mocks = coreMock.createSetup();
|
||||
const [
|
||||
{
|
||||
application: { capabilities },
|
||||
},
|
||||
] = await mocks.getStartServices();
|
||||
deps = {
|
||||
toastNotifications: mockes.notifications.toasts,
|
||||
http: mockes.http,
|
||||
toastNotifications: mocks.notifications.toasts,
|
||||
http: mocks.http,
|
||||
capabilities: {
|
||||
...capabilities,
|
||||
actions: {
|
||||
delete: true,
|
||||
save: true,
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
};
|
||||
actionTypeRegistry.list.mockReturnValue([
|
||||
actionType,
|
||||
|
@ -224,6 +238,8 @@ describe('action_form', () => {
|
|||
},
|
||||
]}
|
||||
toastNotifications={deps!.toastNotifications}
|
||||
docLinks={deps.docLinks}
|
||||
capabilities={deps.capabilities}
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import {
|
|||
EuiHorizontalRule,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { HttpSetup, ToastsApi } from 'kibana/public';
|
||||
import { HttpSetup, ToastsApi, ApplicationStart, DocLinksStart } from 'kibana/public';
|
||||
import { loadActionTypes, loadAllActions as loadConnectors } from '../../lib/action_connector_api';
|
||||
import {
|
||||
IErrorObject,
|
||||
|
@ -57,10 +57,12 @@ interface ActionAccordionFormProps {
|
|||
ToastsApi,
|
||||
'get$' | 'add' | 'remove' | 'addSuccess' | 'addWarning' | 'addDanger' | 'addError'
|
||||
>;
|
||||
docLinks: DocLinksStart;
|
||||
actionTypes?: ActionType[];
|
||||
messageVariables?: string[];
|
||||
defaultActionMessage?: string;
|
||||
setHasActionsDisabled?: (value: boolean) => void;
|
||||
capabilities: ApplicationStart['capabilities'];
|
||||
}
|
||||
|
||||
interface ActiveActionConnectorState {
|
||||
|
@ -81,6 +83,8 @@ export const ActionForm = ({
|
|||
defaultActionMessage,
|
||||
toastNotifications,
|
||||
setHasActionsDisabled,
|
||||
capabilities,
|
||||
docLinks,
|
||||
}: ActionAccordionFormProps) => {
|
||||
const [addModalVisible, setAddModalVisibility] = useState<boolean>(false);
|
||||
const [activeActionItem, setActiveActionItem] = useState<ActiveActionConnectorState | undefined>(
|
||||
|
@ -685,6 +689,8 @@ export const ActionForm = ({
|
|||
actionTypeRegistry={actionTypeRegistry}
|
||||
http={http}
|
||||
toastNotifications={toastNotifications}
|
||||
docLinks={docLinks}
|
||||
capabilities={capabilities}
|
||||
/>
|
||||
) : null}
|
||||
</Fragment>
|
||||
|
|
|
@ -6,17 +6,14 @@
|
|||
import * as React from 'react';
|
||||
import { mountWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import { coreMock } from '../../../../../../../src/core/public/mocks';
|
||||
import {
|
||||
ActionsConnectorsContextProvider,
|
||||
ActionsConnectorsContextValue,
|
||||
} from '../../context/actions_connectors_context';
|
||||
import { ActionsConnectorsContextProvider } from '../../context/actions_connectors_context';
|
||||
import { actionTypeRegistryMock } from '../../action_type_registry.mock';
|
||||
import { ActionTypeMenu } from './action_type_menu';
|
||||
import { ValidationResult } from '../../../types';
|
||||
const actionTypeRegistry = actionTypeRegistryMock.create();
|
||||
|
||||
describe('connector_add_flyout', () => {
|
||||
let deps: ActionsConnectorsContextValue;
|
||||
let deps: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const mockes = coreMock.createSetup();
|
||||
|
@ -37,6 +34,7 @@ describe('connector_add_flyout', () => {
|
|||
},
|
||||
},
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -68,6 +66,7 @@ describe('connector_add_flyout', () => {
|
|||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps!.docLinks,
|
||||
}}
|
||||
>
|
||||
<ActionTypeMenu
|
||||
|
@ -117,6 +116,7 @@ describe('connector_add_flyout', () => {
|
|||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps!.docLinks,
|
||||
}}
|
||||
>
|
||||
<ActionTypeMenu
|
||||
|
@ -166,6 +166,7 @@ describe('connector_add_flyout', () => {
|
|||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps!.docLinks,
|
||||
}}
|
||||
>
|
||||
<ActionTypeMenu
|
||||
|
|
|
@ -7,17 +7,14 @@ import * as React from 'react';
|
|||
import { mountWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import { coreMock } from '../../../../../../../src/core/public/mocks';
|
||||
import { ConnectorAddFlyout } from './connector_add_flyout';
|
||||
import {
|
||||
ActionsConnectorsContextProvider,
|
||||
ActionsConnectorsContextValue,
|
||||
} from '../../context/actions_connectors_context';
|
||||
import { ActionsConnectorsContextProvider } from '../../context/actions_connectors_context';
|
||||
import { actionTypeRegistryMock } from '../../action_type_registry.mock';
|
||||
import { ValidationResult } from '../../../types';
|
||||
|
||||
const actionTypeRegistry = actionTypeRegistryMock.create();
|
||||
|
||||
describe('connector_add_flyout', () => {
|
||||
let deps: ActionsConnectorsContextValue;
|
||||
let deps: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const mocks = coreMock.createSetup();
|
||||
|
@ -38,6 +35,7 @@ describe('connector_add_flyout', () => {
|
|||
},
|
||||
},
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -56,6 +54,7 @@ describe('connector_add_flyout', () => {
|
|||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps!.docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorAddFlyout
|
||||
|
@ -95,6 +94,7 @@ describe('connector_add_flyout', () => {
|
|||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps!.docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorAddFlyout
|
||||
|
@ -154,6 +154,7 @@ describe('connector_add_flyout', () => {
|
|||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps!.docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorAddFlyout
|
||||
|
@ -201,6 +202,7 @@ describe('connector_add_flyout', () => {
|
|||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps!.docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorAddFlyout
|
||||
|
|
|
@ -114,8 +114,6 @@ export const ConnectorAddFlyout = ({
|
|||
connector={connector}
|
||||
dispatch={dispatch}
|
||||
errors={errors}
|
||||
actionTypeRegistry={actionTypeRegistry}
|
||||
http={http}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -9,11 +9,10 @@ import { coreMock } from '../../../../../../../src/core/public/mocks';
|
|||
import { ConnectorAddModal } from './connector_add_modal';
|
||||
import { actionTypeRegistryMock } from '../../action_type_registry.mock';
|
||||
import { ValidationResult, ActionType } from '../../../types';
|
||||
import { ActionsConnectorsContextValue } from '../../context/actions_connectors_context';
|
||||
const actionTypeRegistry = actionTypeRegistryMock.create();
|
||||
|
||||
describe('connector_add_modal', () => {
|
||||
let deps: ActionsConnectorsContextValue;
|
||||
let deps: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const mocks = coreMock.createSetup();
|
||||
|
@ -27,13 +26,14 @@ describe('connector_add_modal', () => {
|
|||
http: mocks.http,
|
||||
capabilities: {
|
||||
...capabilities,
|
||||
actions: {
|
||||
delete: true,
|
||||
save: true,
|
||||
show: true,
|
||||
siem: {
|
||||
'actions:show': true,
|
||||
'actions:save': true,
|
||||
'actions:delete': true,
|
||||
},
|
||||
},
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
};
|
||||
});
|
||||
it('renders connector modal form if addModalVisible is true', () => {
|
||||
|
@ -63,19 +63,19 @@ describe('connector_add_modal', () => {
|
|||
minimumLicenseRequired: 'basic',
|
||||
};
|
||||
|
||||
const wrapper = deps
|
||||
? mountWithIntl(
|
||||
<ConnectorAddModal
|
||||
addModalVisible={true}
|
||||
setAddModalVisibility={() => {}}
|
||||
actionType={actionType}
|
||||
http={deps.http}
|
||||
actionTypeRegistry={deps.actionTypeRegistry}
|
||||
toastNotifications={deps.toastNotifications}
|
||||
/>
|
||||
)
|
||||
: undefined;
|
||||
expect(wrapper?.find('EuiModalHeader')).toHaveLength(1);
|
||||
expect(wrapper?.find('[data-test-subj="saveActionButtonModal"]').exists()).toBeTruthy();
|
||||
const wrapper = mountWithIntl(
|
||||
<ConnectorAddModal
|
||||
addModalVisible={true}
|
||||
setAddModalVisibility={() => {}}
|
||||
actionType={actionType}
|
||||
http={deps!.http}
|
||||
actionTypeRegistry={deps!.actionTypeRegistry}
|
||||
toastNotifications={deps!.toastNotifications}
|
||||
docLinks={deps!.docLinks}
|
||||
capabilities={deps!.capabilities}
|
||||
/>
|
||||
);
|
||||
expect(wrapper.exists('.euiModalHeader')).toBeTruthy();
|
||||
expect(wrapper.exists('[data-test-subj="saveActionButtonModal"]')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
import { EuiButtonEmpty } from '@elastic/eui';
|
||||
import { EuiOverlayMask } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { HttpSetup, ToastsApi } from 'kibana/public';
|
||||
import { HttpSetup, ToastsApi, ApplicationStart, DocLinksStart } from 'kibana/public';
|
||||
import { ActionConnectorForm, validateBaseProperties } from './action_connector_form';
|
||||
import { ActionType, ActionConnector, IErrorObject, ActionTypeModel } from '../../../types';
|
||||
import { connectorReducer } from './connector_reducer';
|
||||
|
@ -25,6 +25,8 @@ import { createActionConnector } from '../../lib/action_connector_api';
|
|||
import { TypeRegistry } from '../../type_registry';
|
||||
import './connector_add_modal.scss';
|
||||
import { PLUGIN } from '../../constants/plugin';
|
||||
import { ActionsConnectorsContextProvider } from '../../context/actions_connectors_context';
|
||||
import { hasSaveActionsCapability } from '../../lib/capabilities';
|
||||
|
||||
interface ConnectorAddModalProps {
|
||||
actionType: ActionType;
|
||||
|
@ -33,10 +35,12 @@ interface ConnectorAddModalProps {
|
|||
postSaveEventHandler?: (savedAction: ActionConnector) => void;
|
||||
http: HttpSetup;
|
||||
actionTypeRegistry: TypeRegistry<ActionTypeModel>;
|
||||
toastNotifications?: Pick<
|
||||
toastNotifications: Pick<
|
||||
ToastsApi,
|
||||
'get$' | 'add' | 'remove' | 'addSuccess' | 'addWarning' | 'addDanger' | 'addError'
|
||||
>;
|
||||
capabilities: ApplicationStart['capabilities'];
|
||||
docLinks: DocLinksStart;
|
||||
}
|
||||
|
||||
export const ConnectorAddModal = ({
|
||||
|
@ -47,6 +51,8 @@ export const ConnectorAddModal = ({
|
|||
http,
|
||||
toastNotifications,
|
||||
actionTypeRegistry,
|
||||
capabilities,
|
||||
docLinks,
|
||||
}: ConnectorAddModalProps) => {
|
||||
let hasErrors = false;
|
||||
const initialConnector = {
|
||||
|
@ -55,6 +61,7 @@ export const ConnectorAddModal = ({
|
|||
secrets: {},
|
||||
} as ActionConnector;
|
||||
const [isSaving, setIsSaving] = useState<boolean>(false);
|
||||
const canSave = hasSaveActionsCapability(capabilities);
|
||||
|
||||
const [{ connector }, dispatch] = useReducer(connectorReducer, { connector: initialConnector });
|
||||
const setConnector = (value: any) => {
|
||||
|
@ -149,17 +156,24 @@ export const ConnectorAddModal = ({
|
|||
</EuiModalHeader>
|
||||
|
||||
<EuiModalBody>
|
||||
<ActionConnectorForm
|
||||
connector={connector}
|
||||
actionTypeName={actionType.name}
|
||||
dispatch={dispatch}
|
||||
serverError={serverError}
|
||||
errors={errors}
|
||||
actionTypeRegistry={actionTypeRegistry}
|
||||
http={http}
|
||||
/>
|
||||
<ActionsConnectorsContextProvider
|
||||
value={{
|
||||
actionTypeRegistry,
|
||||
http,
|
||||
capabilities,
|
||||
toastNotifications,
|
||||
docLinks,
|
||||
}}
|
||||
>
|
||||
<ActionConnectorForm
|
||||
connector={connector}
|
||||
actionTypeName={actionType.name}
|
||||
dispatch={dispatch}
|
||||
serverError={serverError}
|
||||
errors={errors}
|
||||
/>
|
||||
</ActionsConnectorsContextProvider>
|
||||
</EuiModalBody>
|
||||
|
||||
<EuiModalFooter>
|
||||
<EuiButtonEmpty onClick={closeModal}>
|
||||
{i18n.translate(
|
||||
|
@ -169,32 +183,33 @@ export const ConnectorAddModal = ({
|
|||
}
|
||||
)}
|
||||
</EuiButtonEmpty>
|
||||
|
||||
<EuiButton
|
||||
fill
|
||||
color="secondary"
|
||||
data-test-subj="saveActionButtonModal"
|
||||
type="submit"
|
||||
iconType="check"
|
||||
isDisabled={hasErrors}
|
||||
isLoading={isSaving}
|
||||
onClick={async () => {
|
||||
setIsSaving(true);
|
||||
const savedAction = await onActionConnectorSave();
|
||||
setIsSaving(false);
|
||||
if (savedAction) {
|
||||
if (postSaveEventHandler) {
|
||||
postSaveEventHandler(savedAction);
|
||||
{canSave ? (
|
||||
<EuiButton
|
||||
fill
|
||||
color="secondary"
|
||||
data-test-subj="saveActionButtonModal"
|
||||
type="submit"
|
||||
iconType="check"
|
||||
isDisabled={hasErrors}
|
||||
isLoading={isSaving}
|
||||
onClick={async () => {
|
||||
setIsSaving(true);
|
||||
const savedAction = await onActionConnectorSave();
|
||||
setIsSaving(false);
|
||||
if (savedAction) {
|
||||
if (postSaveEventHandler) {
|
||||
postSaveEventHandler(savedAction);
|
||||
}
|
||||
closeModal();
|
||||
}
|
||||
closeModal();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.addModalConnectorForm.saveButtonLabel"
|
||||
defaultMessage="Save"
|
||||
/>
|
||||
</EuiButton>
|
||||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.addModalConnectorForm.saveButtonLabel"
|
||||
defaultMessage="Save"
|
||||
/>
|
||||
</EuiButton>
|
||||
) : null}
|
||||
</EuiModalFooter>
|
||||
</EuiModal>
|
||||
</EuiOverlayMask>
|
||||
|
|
|
@ -37,6 +37,7 @@ describe('connector_edit_flyout', () => {
|
|||
},
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
alertTypeRegistry: {} as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -80,6 +81,7 @@ describe('connector_edit_flyout', () => {
|
|||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps.docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorEditFlyout
|
||||
|
@ -136,6 +138,7 @@ describe('connector_edit_flyout', () => {
|
|||
reloadConnectors: () => {
|
||||
return new Promise<void>(() => {});
|
||||
},
|
||||
docLinks: deps.docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorEditFlyout
|
||||
|
|
|
@ -47,6 +47,7 @@ export const ConnectorEditFlyout = ({
|
|||
capabilities,
|
||||
actionTypeRegistry,
|
||||
reloadConnectors,
|
||||
docLinks,
|
||||
} = useActionsConnectorsContext();
|
||||
const canSave = hasSaveActionsCapability(capabilities);
|
||||
const closeFlyout = useCallback(() => setEditFlyoutVisibility(false), [setEditFlyoutVisibility]);
|
||||
|
@ -181,8 +182,6 @@ export const ConnectorEditFlyout = ({
|
|||
errors={errors}
|
||||
actionTypeName={connector.actionType}
|
||||
dispatch={dispatch}
|
||||
actionTypeRegistry={actionTypeRegistry}
|
||||
http={http}
|
||||
/>
|
||||
) : (
|
||||
<Fragment>
|
||||
|
@ -194,7 +193,10 @@ export const ConnectorEditFlyout = ({
|
|||
}
|
||||
)}
|
||||
</EuiText>
|
||||
<EuiLink href="https://www.elastic.co/guide" target="_blank">
|
||||
<EuiLink
|
||||
href={`${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/pre-configured-connectors.html`}
|
||||
target="_blank"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.editConnectorForm.preconfiguredHelpLabel"
|
||||
defaultMessage="Learn more about preconfigured connectors."
|
||||
|
|
|
@ -32,7 +32,13 @@ import { ActionConnector, ActionConnectorTableItem, ActionTypeIndex } from '../.
|
|||
import { EmptyConnectorsPrompt } from '../../../components/prompts/empty_connectors_prompt';
|
||||
|
||||
export const ActionsConnectorsList: React.FunctionComponent = () => {
|
||||
const { http, toastNotifications, capabilities, actionTypeRegistry } = useAppDependencies();
|
||||
const {
|
||||
http,
|
||||
toastNotifications,
|
||||
capabilities,
|
||||
actionTypeRegistry,
|
||||
docLinks,
|
||||
} = useAppDependencies();
|
||||
const canDelete = hasDeleteActionsCapability(capabilities);
|
||||
const canSave = hasSaveActionsCapability(capabilities);
|
||||
|
||||
|
@ -394,6 +400,7 @@ export const ActionsConnectorsList: React.FunctionComponent = () => {
|
|||
capabilities,
|
||||
toastNotifications,
|
||||
reloadConnectors: loadActions,
|
||||
docLinks,
|
||||
}}
|
||||
>
|
||||
<ConnectorAddFlyout
|
||||
|
|
|
@ -138,6 +138,7 @@ export const AlertDetails: React.FunctionComponent<AlertDetailsProps> = ({
|
|||
charts,
|
||||
dataFieldsFormats: dataPlugin.fieldFormats,
|
||||
reloadAlerts: setAlert,
|
||||
capabilities,
|
||||
}}
|
||||
>
|
||||
<AlertEdit
|
||||
|
|
|
@ -41,11 +41,16 @@ describe('alert_add', () => {
|
|||
let wrapper: ReactWrapper<any>;
|
||||
|
||||
async function setup() {
|
||||
const mockes = coreMock.createSetup();
|
||||
const mocks = coreMock.createSetup();
|
||||
const [
|
||||
{
|
||||
application: { capabilities },
|
||||
},
|
||||
] = await mocks.getStartServices();
|
||||
deps = {
|
||||
toastNotifications: mockes.notifications.toasts,
|
||||
http: mockes.http,
|
||||
uiSettings: mockes.uiSettings,
|
||||
toastNotifications: mocks.notifications.toasts,
|
||||
http: mocks.http,
|
||||
uiSettings: mocks.uiSettings,
|
||||
dataPlugin: dataPluginMock.createStartContract(),
|
||||
charts: chartPluginMock.createStartContract(),
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
|
@ -53,7 +58,7 @@ describe('alert_add', () => {
|
|||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
};
|
||||
|
||||
mockes.http.get.mockResolvedValue({
|
||||
mocks.http.get.mockResolvedValue({
|
||||
isSufficientlySecure: true,
|
||||
hasPermanentEncryptionKey: true,
|
||||
});
|
||||
|
@ -104,6 +109,14 @@ describe('alert_add', () => {
|
|||
uiSettings: deps.uiSettings,
|
||||
docLinks: deps.docLinks,
|
||||
metadata: { test: 'some value', fields: ['test'] },
|
||||
capabilities: {
|
||||
...capabilities,
|
||||
actions: {
|
||||
delete: true,
|
||||
save: true,
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<AlertAdd
|
||||
|
|
|
@ -27,6 +27,11 @@ describe('alert_edit', () => {
|
|||
});
|
||||
|
||||
async function setup() {
|
||||
const [
|
||||
{
|
||||
application: { capabilities },
|
||||
},
|
||||
] = await mockedCoreSetup.getStartServices();
|
||||
deps = {
|
||||
toastNotifications: mockedCoreSetup.notifications.toasts,
|
||||
http: mockedCoreSetup.http,
|
||||
|
@ -34,6 +39,7 @@ describe('alert_edit', () => {
|
|||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
alertTypeRegistry: alertTypeRegistry as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
capabilities,
|
||||
};
|
||||
|
||||
mockedCoreSetup.http.get.mockResolvedValue({
|
||||
|
@ -122,6 +128,7 @@ describe('alert_edit', () => {
|
|||
toastNotifications: deps!.toastNotifications,
|
||||
uiSettings: deps!.uiSettings,
|
||||
docLinks: deps.docLinks,
|
||||
capabilities: deps!.capabilities,
|
||||
}}
|
||||
>
|
||||
<AlertEdit
|
||||
|
|
|
@ -46,14 +46,20 @@ describe('alert_form', () => {
|
|||
let wrapper: ReactWrapper<any>;
|
||||
|
||||
async function setup() {
|
||||
const mockes = coreMock.createSetup();
|
||||
const mocks = coreMock.createSetup();
|
||||
const [
|
||||
{
|
||||
application: { capabilities },
|
||||
},
|
||||
] = await mocks.getStartServices();
|
||||
deps = {
|
||||
toastNotifications: mockes.notifications.toasts,
|
||||
http: mockes.http,
|
||||
uiSettings: mockes.uiSettings,
|
||||
toastNotifications: mocks.notifications.toasts,
|
||||
http: mocks.http,
|
||||
uiSettings: mocks.uiSettings,
|
||||
actionTypeRegistry: actionTypeRegistry as any,
|
||||
alertTypeRegistry: alertTypeRegistry as any,
|
||||
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
|
||||
capabilities,
|
||||
};
|
||||
alertTypeRegistry.list.mockReturnValue([alertType]);
|
||||
alertTypeRegistry.has.mockReturnValue(true);
|
||||
|
@ -86,6 +92,7 @@ describe('alert_form', () => {
|
|||
alertTypeRegistry: deps!.alertTypeRegistry,
|
||||
toastNotifications: deps!.toastNotifications,
|
||||
uiSettings: deps!.uiSettings,
|
||||
capabilities: deps!.capabilities,
|
||||
}}
|
||||
>
|
||||
<AlertForm alert={initialAlert} dispatch={() => {}} errors={{ name: [], interval: [] }} />
|
||||
|
@ -166,6 +173,7 @@ describe('alert_form', () => {
|
|||
alertTypeRegistry: deps!.alertTypeRegistry,
|
||||
toastNotifications: deps!.toastNotifications,
|
||||
uiSettings: deps!.uiSettings,
|
||||
capabilities: deps!.capabilities,
|
||||
}}
|
||||
>
|
||||
<AlertForm alert={initialAlert} dispatch={() => {}} errors={{ name: [], interval: [] }} />
|
||||
|
|
|
@ -87,7 +87,14 @@ export const AlertForm = ({
|
|||
setHasActionsDisabled,
|
||||
}: AlertFormProps) => {
|
||||
const alertsContext = useAlertsContext();
|
||||
const { http, toastNotifications, alertTypeRegistry, actionTypeRegistry } = alertsContext;
|
||||
const {
|
||||
http,
|
||||
toastNotifications,
|
||||
alertTypeRegistry,
|
||||
actionTypeRegistry,
|
||||
docLinks,
|
||||
capabilities,
|
||||
} = alertsContext;
|
||||
|
||||
const [alertTypeModel, setAlertTypeModel] = useState<AlertTypeModel | null>(
|
||||
alert.alertTypeId ? alertTypeRegistry.get(alert.alertTypeId) : null
|
||||
|
@ -245,6 +252,8 @@ export const AlertForm = ({
|
|||
actionTypeRegistry={actionTypeRegistry}
|
||||
defaultActionMessage={alertTypeModel?.defaultActionMessage}
|
||||
toastNotifications={toastNotifications}
|
||||
docLinks={docLinks}
|
||||
capabilities={capabilities}
|
||||
/>
|
||||
) : null}
|
||||
</Fragment>
|
||||
|
|
|
@ -435,6 +435,7 @@ export const AlertsList: React.FunctionComponent = () => {
|
|||
docLinks,
|
||||
charts,
|
||||
dataFieldsFormats: dataPlugin.fieldFormats,
|
||||
capabilities,
|
||||
}}
|
||||
>
|
||||
<AlertAdd
|
||||
|
|
|
@ -18,6 +18,7 @@ export const UptimeAlertsContextProvider: React.FC = ({ children }) => {
|
|||
triggers_actions_ui: { actionTypeRegistry, alertTypeRegistry },
|
||||
uiSettings,
|
||||
docLinks,
|
||||
application: { capabilities },
|
||||
},
|
||||
} = useKibana();
|
||||
|
||||
|
@ -32,6 +33,7 @@ export const UptimeAlertsContextProvider: React.FC = ({ children }) => {
|
|||
http,
|
||||
toastNotifications: notifications?.toasts,
|
||||
uiSettings,
|
||||
capabilities,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue