mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[RAM] Move Connectors to own page (#142485)
* Move Connectors to own page * Move create connector button to header * Update permissions IDs * Fix some tests * Test fixes * Fix more tests * Fix more tests * Fix FTR 7 * Fix jest * Fix FTR 4 * Fix FTR 6 * Fix translations * Fix breadcrumbs * Fix empty prompt design * Update empty prompt text * Update import warning url * Add documentation buttons Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
42a7a09267
commit
ec98f01c9f
29 changed files with 457 additions and 216 deletions
|
@ -28,7 +28,7 @@ export const ACTIONS_FEATURE = {
|
|||
app: [],
|
||||
order: FEATURE_ORDER,
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
insightsAndAlerting: ['triggersActions', 'triggersActionsConnectors'],
|
||||
},
|
||||
privileges: {
|
||||
all: {
|
||||
|
@ -36,7 +36,7 @@ export const ACTIONS_FEATURE = {
|
|||
api: [],
|
||||
catalogue: [],
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
insightsAndAlerting: ['triggersActions', 'triggersActionsConnectors'],
|
||||
},
|
||||
savedObject: {
|
||||
all: [
|
||||
|
@ -53,7 +53,7 @@ export const ACTIONS_FEATURE = {
|
|||
api: [],
|
||||
catalogue: [],
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
insightsAndAlerting: ['triggersActions', 'triggersActionsConnectors'],
|
||||
},
|
||||
savedObject: {
|
||||
// action execution requires 'read' over `actions`, but 'all' over `action_task_params`
|
||||
|
|
|
@ -29,7 +29,7 @@ export function getImportWarnings(
|
|||
{
|
||||
type: 'action_required',
|
||||
message,
|
||||
actionPath: '/app/management/insightsAndAlerting/triggersActions/connectors',
|
||||
actionPath: '/app/management/insightsAndAlerting/triggersActionsConnectors',
|
||||
buttonLabel: GO_TO_CONNECTORS_BUTTON_LABLE,
|
||||
} as SavedObjectsImportWarning,
|
||||
];
|
||||
|
|
|
@ -67,7 +67,7 @@ export class CasesUiPlugin
|
|||
plugins.management.sections.section.insightsAndAlerting.registerApp({
|
||||
id: APP_ID,
|
||||
title: APP_TITLE,
|
||||
order: 0,
|
||||
order: 1,
|
||||
async mount(params: ManagementAppMountParams) {
|
||||
const [coreStart, pluginsStart] = (await core.getStartServices()) as [
|
||||
CoreStart,
|
||||
|
|
|
@ -23,7 +23,7 @@ export function registerManagementSection(
|
|||
title: i18n.translate('xpack.ml.management.jobsListTitle', {
|
||||
defaultMessage: 'Machine Learning',
|
||||
}),
|
||||
order: 2,
|
||||
order: 4,
|
||||
async mount(params: ManagementAppMountParams) {
|
||||
const { mountApp } = await import('./jobs_list');
|
||||
return mountApp(core, params, deps);
|
||||
|
|
|
@ -172,7 +172,7 @@ export class ReportingPublicPlugin
|
|||
management.sections.section.insightsAndAlerting.registerApp({
|
||||
id: 'reporting',
|
||||
title: this.title,
|
||||
order: 1,
|
||||
order: 3,
|
||||
mount: async (params) => {
|
||||
params.setBreadcrumbs([{ text: this.breadcrumbText }]);
|
||||
const [[start, startDeps], { mountManagementSection }] = await Promise.all([
|
||||
|
|
|
@ -32297,7 +32297,6 @@
|
|||
"xpack.triggersActionsUI.fieldBrowser.viewSelected": "sélectionné",
|
||||
"xpack.triggersActionsUI.home.appTitle": "Règles et connecteurs",
|
||||
"xpack.triggersActionsUI.home.breadcrumbTitle": "Règles et connecteurs",
|
||||
"xpack.triggersActionsUI.home.connectorsTabTitle": "Connecteurs",
|
||||
"xpack.triggersActionsUI.home.docsLinkText": "Documentation",
|
||||
"xpack.triggersActionsUI.home.rulesTabTitle": "Règles",
|
||||
"xpack.triggersActionsUI.home.sectionDescription": "Détecter les conditions à l'aide des règles, et entreprendre des actions à l'aide des connecteurs.",
|
||||
|
|
|
@ -32271,7 +32271,6 @@
|
|||
"xpack.triggersActionsUI.fieldBrowser.viewSelected": "選択済み",
|
||||
"xpack.triggersActionsUI.home.appTitle": "ルールとコネクター",
|
||||
"xpack.triggersActionsUI.home.breadcrumbTitle": "ルールとコネクター",
|
||||
"xpack.triggersActionsUI.home.connectorsTabTitle": "コネクター",
|
||||
"xpack.triggersActionsUI.home.docsLinkText": "ドキュメント",
|
||||
"xpack.triggersActionsUI.home.rulesTabTitle": "ルール",
|
||||
"xpack.triggersActionsUI.home.sectionDescription": "ルールを使用して条件を検出し、コネクターを使用してアクションを実行します。",
|
||||
|
|
|
@ -32308,7 +32308,6 @@
|
|||
"xpack.triggersActionsUI.fieldBrowser.viewSelected": "已选定",
|
||||
"xpack.triggersActionsUI.home.appTitle": "规则和连接器",
|
||||
"xpack.triggersActionsUI.home.breadcrumbTitle": "规则和连接器",
|
||||
"xpack.triggersActionsUI.home.connectorsTabTitle": "连接器",
|
||||
"xpack.triggersActionsUI.home.docsLinkText": "文档",
|
||||
"xpack.triggersActionsUI.home.rulesTabTitle": "规则",
|
||||
"xpack.triggersActionsUI.home.sectionDescription": "使规则检测条件,并使用连接器采取操作。",
|
||||
|
|
|
@ -31,11 +31,17 @@ import {
|
|||
AlertsTableConfigurationRegistryContract,
|
||||
RuleTypeRegistryContract,
|
||||
} from '../types';
|
||||
import { Section, routeToRuleDetails, legacyRouteToRuleDetails } from './constants';
|
||||
import {
|
||||
Section,
|
||||
routeToRuleDetails,
|
||||
legacyRouteToRuleDetails,
|
||||
routeToConnectors,
|
||||
} from './constants';
|
||||
|
||||
import { setDataViewsService } from '../common/lib/data_apis';
|
||||
import { KibanaContextProvider, useKibana } from '../common/lib/kibana';
|
||||
import { ConnectorProvider } from './context/connector_context';
|
||||
import { CONNECTORS_PLUGIN_ID } from '../common/constants';
|
||||
|
||||
const TriggersActionsUIHome = lazy(() => import('./home'));
|
||||
const RuleDetailsRoute = lazy(
|
||||
|
@ -73,7 +79,7 @@ export const renderApp = (deps: TriggersAndActionsUiServices) => {
|
|||
|
||||
export const App = ({ deps }: { deps: TriggersAndActionsUiServices }) => {
|
||||
const { dataViews, uiSettings, theme$ } = deps;
|
||||
const sections: Section[] = ['rules', 'connectors', 'logs', 'alerts'];
|
||||
const sections: Section[] = ['rules', 'logs', 'alerts'];
|
||||
const isDarkMode = useObservable<boolean>(uiSettings.get$('theme:darkMode'));
|
||||
|
||||
const sectionsRegex = sections.join('|');
|
||||
|
@ -96,6 +102,7 @@ export const App = ({ deps }: { deps: TriggersAndActionsUiServices }) => {
|
|||
export const AppWithoutRouter = ({ sectionsRegex }: { sectionsRegex: string }) => {
|
||||
const {
|
||||
actions: { validateEmailAddresses },
|
||||
application: { navigateToApp },
|
||||
} = useKibana().services;
|
||||
|
||||
return (
|
||||
|
@ -114,6 +121,15 @@ export const AppWithoutRouter = ({ sectionsRegex }: { sectionsRegex: string }) =
|
|||
path={legacyRouteToRuleDetails}
|
||||
render={({ match }) => <Redirect to={`/rule/${match.params.alertId}`} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={routeToConnectors}
|
||||
render={() => {
|
||||
navigateToApp(`management/insightsAndAlerting/${CONNECTORS_PLUGIN_ID}`);
|
||||
return null;
|
||||
}}
|
||||
/>
|
||||
|
||||
<Redirect from={'/'} to="rules" />
|
||||
<Redirect from={'/alerts'} to="rules" />
|
||||
</Switch>
|
||||
|
|
|
@ -7,11 +7,25 @@
|
|||
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import React from 'react';
|
||||
import { EuiButton, EuiEmptyPrompt, EuiIcon, EuiSpacer, EuiTitle } from '@elastic/eui';
|
||||
import {
|
||||
EuiButton,
|
||||
EuiButtonEmpty,
|
||||
EuiPageTemplate,
|
||||
EuiIcon,
|
||||
EuiSpacer,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import { DocLinksStart } from '@kbn/core-doc-links-browser';
|
||||
import './empty_connectors_prompt.scss';
|
||||
|
||||
export const EmptyConnectorsPrompt = ({ onCTAClicked }: { onCTAClicked: () => void }) => (
|
||||
<EuiEmptyPrompt
|
||||
export const EmptyConnectorsPrompt = ({
|
||||
onCTAClicked,
|
||||
docLinks,
|
||||
}: {
|
||||
onCTAClicked: () => void;
|
||||
docLinks: DocLinksStart;
|
||||
}) => (
|
||||
<EuiPageTemplate.EmptyPrompt
|
||||
data-test-subj="createFirstConnectorEmptyPrompt"
|
||||
title={
|
||||
<>
|
||||
|
@ -33,24 +47,39 @@ export const EmptyConnectorsPrompt = ({ onCTAClicked }: { onCTAClicked: () => vo
|
|||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.components.emptyConnectorsPrompt.addConnectorEmptyBody"
|
||||
defaultMessage="Configure email, Slack, Elasticsearch, and third-party services that Kibana runs."
|
||||
defaultMessage="Configure various third-party services to Kibana."
|
||||
/>
|
||||
</p>
|
||||
}
|
||||
actions={
|
||||
<EuiButton
|
||||
data-test-subj="createFirstActionButton"
|
||||
key="create-action"
|
||||
fill
|
||||
iconType="plusInCircle"
|
||||
iconSide="left"
|
||||
onClick={onCTAClicked}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.components.emptyConnectorsPrompt.addConnectorButtonLabel"
|
||||
defaultMessage="Create connector"
|
||||
/>
|
||||
</EuiButton>
|
||||
<>
|
||||
<EuiButton
|
||||
data-test-subj="createFirstActionButton"
|
||||
key="create-action"
|
||||
fill
|
||||
iconType="plusInCircle"
|
||||
iconSide="left"
|
||||
onClick={onCTAClicked}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.components.emptyConnectorsPrompt.addConnectorButtonLabel"
|
||||
defaultMessage="Create connector"
|
||||
/>
|
||||
</EuiButton>
|
||||
<br />
|
||||
<EuiButtonEmpty
|
||||
data-test-subj="documentationButton"
|
||||
key="documentation-button"
|
||||
target="_blank"
|
||||
href={docLinks.links.alerting.connectors}
|
||||
iconType="help"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.actionsConnectorsList.documentationButtonLabel"
|
||||
defaultMessage="Documentation"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { lazy } from 'react';
|
||||
import { Switch, Route, Router } from 'react-router-dom';
|
||||
import { ChromeBreadcrumb, CoreStart, CoreTheme, ScopedHistory } from '@kbn/core/public';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
import useObservable from 'react-use/lib/useObservable';
|
||||
import { Observable } from 'rxjs';
|
||||
import { KibanaFeature } from '@kbn/features-plugin/common';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||
import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
|
||||
import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
|
||||
import { PluginStartContract as AlertingStart } from '@kbn/alerting-plugin/public';
|
||||
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
||||
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common';
|
||||
import { ActionsPublicPluginSetup } from '@kbn/actions-plugin/public';
|
||||
import { suspendedComponentWithProps } from './lib/suspended_component_with_props';
|
||||
import {
|
||||
ActionTypeRegistryContract,
|
||||
AlertsTableConfigurationRegistryContract,
|
||||
RuleTypeRegistryContract,
|
||||
} from '../types';
|
||||
|
||||
import { setDataViewsService } from '../common/lib/data_apis';
|
||||
import { KibanaContextProvider, useKibana } from '../common/lib/kibana';
|
||||
import { ConnectorProvider } from './context/connector_context';
|
||||
|
||||
const ActionsConnectorsList = lazy(
|
||||
() => import('./sections/actions_connectors_list/components/actions_connectors_list')
|
||||
);
|
||||
|
||||
export interface TriggersAndActionsUiServices extends CoreStart {
|
||||
actions: ActionsPublicPluginSetup;
|
||||
data: DataPublicPluginStart;
|
||||
dataViews: DataViewsPublicPluginStart;
|
||||
dataViewEditor: DataViewEditorStart;
|
||||
charts: ChartsPluginStart;
|
||||
alerting?: AlertingStart;
|
||||
spaces?: SpacesPluginStart;
|
||||
storage?: Storage;
|
||||
isCloud: boolean;
|
||||
setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void;
|
||||
actionTypeRegistry: ActionTypeRegistryContract;
|
||||
ruleTypeRegistry: RuleTypeRegistryContract;
|
||||
alertsTableConfigurationRegistry: AlertsTableConfigurationRegistryContract;
|
||||
history: ScopedHistory;
|
||||
kibanaFeatures: KibanaFeature[];
|
||||
element: HTMLElement;
|
||||
theme$: Observable<CoreTheme>;
|
||||
unifiedSearch: UnifiedSearchPublicPluginStart;
|
||||
}
|
||||
|
||||
export const renderApp = (deps: TriggersAndActionsUiServices) => {
|
||||
const { element } = deps;
|
||||
render(<App deps={deps} />, element);
|
||||
return () => {
|
||||
unmountComponentAtNode(element);
|
||||
};
|
||||
};
|
||||
|
||||
export const App = ({ deps }: { deps: TriggersAndActionsUiServices }) => {
|
||||
const { dataViews, uiSettings, theme$ } = deps;
|
||||
const isDarkMode = useObservable<boolean>(uiSettings.get$('theme:darkMode'));
|
||||
|
||||
setDataViewsService(dataViews);
|
||||
return (
|
||||
<I18nProvider>
|
||||
<EuiThemeProvider darkMode={isDarkMode}>
|
||||
<KibanaThemeProvider theme$={theme$}>
|
||||
<KibanaContextProvider services={{ ...deps }}>
|
||||
<Router history={deps.history}>
|
||||
<AppWithoutRouter />
|
||||
</Router>
|
||||
</KibanaContextProvider>
|
||||
</KibanaThemeProvider>
|
||||
</EuiThemeProvider>
|
||||
</I18nProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export const AppWithoutRouter = () => {
|
||||
const {
|
||||
actions: { validateEmailAddresses },
|
||||
} = useKibana().services;
|
||||
|
||||
return (
|
||||
<ConnectorProvider value={{ services: { validateEmailAddresses } }}>
|
||||
<Switch>
|
||||
<Route path={'/'} component={suspendedComponentWithProps(ActionsConnectorsList, 'xl')} />
|
||||
</Switch>
|
||||
</ConnectorProvider>
|
||||
);
|
||||
};
|
|
@ -9,7 +9,7 @@ export const PLUGIN = {
|
|||
ID: 'triggersActionsUi',
|
||||
getI18nName: (i18n: any): string => {
|
||||
return i18n.translate('xpack.triggersActionsUI.appName', {
|
||||
defaultMessage: 'Rules and Connectors',
|
||||
defaultMessage: 'Rules',
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -69,8 +69,8 @@ describe('home', () => {
|
|||
|
||||
let home = mountWithIntl(<TriggersActionsUIHome {...props} />);
|
||||
|
||||
// Just rules/connectors
|
||||
expect(home.find('.euiTab__content').length).toBe(3);
|
||||
// Just rules/logs
|
||||
expect(home.find('.euiTab__content').length).toBe(2);
|
||||
|
||||
(getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation((feature: string) => {
|
||||
if (feature === 'internalAlertsTable') {
|
||||
|
@ -81,6 +81,6 @@ describe('home', () => {
|
|||
|
||||
home = mountWithIntl(<TriggersActionsUIHome {...props} />);
|
||||
// alerts now too!
|
||||
expect(home.find('.euiTab__content').length).toBe(4);
|
||||
expect(home.find('.euiTab__content').length).toBe(3);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,25 +11,15 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { EuiSpacer, EuiButtonEmpty, EuiPageHeader } from '@elastic/eui';
|
||||
|
||||
import { getIsExperimentalFeatureEnabled } from '../common/get_experimental_features';
|
||||
import {
|
||||
Section,
|
||||
routeToConnectors,
|
||||
routeToRules,
|
||||
routeToInternalAlerts,
|
||||
routeToLogs,
|
||||
} from './constants';
|
||||
import { Section, routeToRules, routeToInternalAlerts, routeToLogs } from './constants';
|
||||
import { getAlertingSectionBreadcrumb } from './lib/breadcrumb';
|
||||
import { getCurrentDocTitle } from './lib/doc_title';
|
||||
import { hasShowActionsCapability } from './lib/capabilities';
|
||||
|
||||
import { HealthCheck } from './components/health_check';
|
||||
import { HealthContextProvider } from './context/health_context';
|
||||
import { useKibana } from '../common/lib/kibana';
|
||||
import { suspendedComponentWithProps } from './lib/suspended_component_with_props';
|
||||
|
||||
const ActionsConnectorsList = lazy(
|
||||
() => import('./sections/actions_connectors_list/components/actions_connectors_list')
|
||||
);
|
||||
const RulesList = lazy(() => import('./sections/rules_list/components/rules_list'));
|
||||
const LogsList = lazy(() => import('./sections/logs_list/components/logs_list'));
|
||||
const AlertsPage = lazy(() => import('./sections/alerts_table/alerts_page'));
|
||||
|
@ -44,16 +34,9 @@ export const TriggersActionsUIHome: React.FunctionComponent<RouteComponentProps<
|
|||
},
|
||||
history,
|
||||
}) => {
|
||||
const {
|
||||
chrome,
|
||||
application: { capabilities },
|
||||
|
||||
setBreadcrumbs,
|
||||
docLinks,
|
||||
} = useKibana().services;
|
||||
const { chrome, setBreadcrumbs, docLinks } = useKibana().services;
|
||||
const isInternalAlertsTableEnabled = getIsExperimentalFeatureEnabled('internalAlertsTable');
|
||||
|
||||
const canShowActions = hasShowActionsCapability(capabilities);
|
||||
const tabs: Array<{
|
||||
id: Section;
|
||||
name: React.ReactNode;
|
||||
|
@ -66,18 +49,6 @@ export const TriggersActionsUIHome: React.FunctionComponent<RouteComponentProps<
|
|||
),
|
||||
});
|
||||
|
||||
if (canShowActions) {
|
||||
tabs.push({
|
||||
id: 'connectors',
|
||||
name: (
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.home.connectorsTabTitle"
|
||||
defaultMessage="Connectors"
|
||||
/>
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
tabs.push({
|
||||
id: 'logs',
|
||||
name: <FormattedMessage id="xpack.triggersActionsUI.home.logsTabTitle" defaultMessage="Logs" />,
|
||||
|
@ -111,10 +82,7 @@ export const TriggersActionsUIHome: React.FunctionComponent<RouteComponentProps<
|
|||
bottomBorder
|
||||
pageTitle={
|
||||
<span data-test-subj="appTitle">
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.home.appTitle"
|
||||
defaultMessage="Rules and Connectors"
|
||||
/>
|
||||
<FormattedMessage id="xpack.triggersActionsUI.home.appTitle" defaultMessage="Rules" />
|
||||
</span>
|
||||
}
|
||||
rightSideItems={[
|
||||
|
@ -133,7 +101,7 @@ export const TriggersActionsUIHome: React.FunctionComponent<RouteComponentProps<
|
|||
description={
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.home.sectionDescription"
|
||||
defaultMessage="Detect conditions using rules, and take actions using connectors."
|
||||
defaultMessage="Detect conditions using rules."
|
||||
/>
|
||||
}
|
||||
tabs={tabs.map((tab) => ({
|
||||
|
@ -155,13 +123,6 @@ export const TriggersActionsUIHome: React.FunctionComponent<RouteComponentProps<
|
|||
path={routeToLogs}
|
||||
component={suspendedComponentWithProps(LogsList, 'xl')}
|
||||
/>
|
||||
{canShowActions && (
|
||||
<Route
|
||||
exact
|
||||
path={routeToConnectors}
|
||||
component={suspendedComponentWithProps(ActionsConnectorsList, 'xl')}
|
||||
/>
|
||||
)}
|
||||
<Route
|
||||
exact
|
||||
path={routeToRules}
|
||||
|
|
|
@ -25,7 +25,7 @@ describe('getAlertingSectionBreadcrumb', () => {
|
|||
});
|
||||
expect(getAlertingSectionBreadcrumb('home', true)).toMatchObject({
|
||||
text: i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', {
|
||||
defaultMessage: 'Rules and Connectors',
|
||||
defaultMessage: 'Rules',
|
||||
}),
|
||||
href: `${routeToHome}`,
|
||||
});
|
||||
|
@ -44,7 +44,7 @@ describe('getAlertingSectionBreadcrumb', () => {
|
|||
});
|
||||
expect(getAlertingSectionBreadcrumb('home', false)).toMatchObject({
|
||||
text: i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', {
|
||||
defaultMessage: 'Rules and Connectors',
|
||||
defaultMessage: 'Rules',
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { routeToHome, routeToConnectors, routeToRules } from '../constants';
|
||||
import { routeToHome, routeToConnectors, routeToRules, routeToLogs } from '../constants';
|
||||
|
||||
export const getAlertingSectionBreadcrumb = (
|
||||
type: string,
|
||||
|
@ -14,6 +14,17 @@ export const getAlertingSectionBreadcrumb = (
|
|||
): { text: string; href?: string } => {
|
||||
// Home and sections
|
||||
switch (type) {
|
||||
case 'logs':
|
||||
return {
|
||||
text: i18n.translate('xpack.triggersActionsUI.logs.breadcrumbTitle', {
|
||||
defaultMessage: 'Logs',
|
||||
}),
|
||||
...(returnHref
|
||||
? {
|
||||
href: `${routeToLogs}`,
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
case 'connectors':
|
||||
return {
|
||||
text: i18n.translate('xpack.triggersActionsUI.connectors.breadcrumbTitle', {
|
||||
|
@ -39,7 +50,7 @@ export const getAlertingSectionBreadcrumb = (
|
|||
default:
|
||||
return {
|
||||
text: i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', {
|
||||
defaultMessage: 'Rules and Connectors',
|
||||
defaultMessage: 'Rules',
|
||||
}),
|
||||
...(returnHref
|
||||
? {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { getCurrentDocTitle } from './doc_title';
|
|||
|
||||
describe('getCurrentDocTitle', () => {
|
||||
test('if change calls return the proper doc title ', async () => {
|
||||
expect(getCurrentDocTitle('home') === 'Rules and Connectors').toBeTruthy();
|
||||
expect(getCurrentDocTitle('home') === 'Rules').toBeTruthy();
|
||||
expect(getCurrentDocTitle('connectors') === 'Connectors').toBeTruthy();
|
||||
expect(getCurrentDocTitle('rules') === 'Rules').toBeTruthy();
|
||||
});
|
||||
|
|
|
@ -11,6 +11,11 @@ export const getCurrentDocTitle = (page: string): string => {
|
|||
let updatedTitle: string;
|
||||
|
||||
switch (page) {
|
||||
case 'logs':
|
||||
updatedTitle = i18n.translate('xpack.triggersActionsUI.logs.breadcrumbTitle', {
|
||||
defaultMessage: 'Logs',
|
||||
});
|
||||
break;
|
||||
case 'connectors':
|
||||
updatedTitle = i18n.translate('xpack.triggersActionsUI.connectors.breadcrumbTitle', {
|
||||
defaultMessage: 'Connectors',
|
||||
|
@ -23,7 +28,7 @@ export const getCurrentDocTitle = (page: string): string => {
|
|||
break;
|
||||
default:
|
||||
updatedTitle = i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', {
|
||||
defaultMessage: 'Rules and Connectors',
|
||||
defaultMessage: 'Rules',
|
||||
});
|
||||
}
|
||||
return updatedTitle;
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
Criteria,
|
||||
EuiButtonEmpty,
|
||||
EuiBadge,
|
||||
EuiPageTemplate,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { omit } from 'lodash';
|
||||
|
@ -52,6 +53,8 @@ import {
|
|||
} from '../../../../common/connectors_selection';
|
||||
import { CreateConnectorFlyout } from '../../action_connector_form/create_connector_flyout';
|
||||
import { EditConnectorFlyout } from '../../action_connector_form/edit_connector_flyout';
|
||||
import { getAlertingSectionBreadcrumb } from '../../../lib/breadcrumb';
|
||||
import { getCurrentDocTitle } from '../../../lib/doc_title';
|
||||
|
||||
const ConnectorIconTipWithSpacing = withTheme(({ theme }: { theme: EuiTheme }) => {
|
||||
return (
|
||||
|
@ -83,6 +86,9 @@ const ActionsConnectorsList: React.FunctionComponent = () => {
|
|||
notifications: { toasts },
|
||||
application: { capabilities },
|
||||
actionTypeRegistry,
|
||||
setBreadcrumbs,
|
||||
chrome,
|
||||
docLinks,
|
||||
} = useKibana().services;
|
||||
const canDelete = hasDeleteActionsCapability(capabilities);
|
||||
const canExecute = hasExecuteActionsCapability(capabilities);
|
||||
|
@ -107,6 +113,12 @@ const ActionsConnectorsList: React.FunctionComponent = () => {
|
|||
}, []);
|
||||
const [showWarningText, setShowWarningText] = useState<boolean>(false);
|
||||
|
||||
// Set breadcrumb and page title
|
||||
useEffect(() => {
|
||||
setBreadcrumbs([getAlertingSectionBreadcrumb('connectors')]);
|
||||
chrome.docTitle.change(getCurrentDocTitle('connectors'));
|
||||
}, [chrome, setBreadcrumbs]);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
|
@ -428,110 +440,144 @@ const ActionsConnectorsList: React.FunctionComponent = () => {
|
|||
/>
|
||||
</EuiButton>,
|
||||
],
|
||||
toolsRight: canSave
|
||||
? [
|
||||
<EuiButton
|
||||
data-test-subj="createActionButton"
|
||||
key="create-action"
|
||||
fill
|
||||
onClick={() => setAddFlyoutVisibility(true)}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.actionsConnectorsList.addActionButtonLabel"
|
||||
defaultMessage="Create connector"
|
||||
/>
|
||||
</EuiButton>,
|
||||
]
|
||||
: [],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<section data-test-subj="actionsList">
|
||||
<DeleteModalConfirmation
|
||||
data-test-subj="deleteConnectorsConfirmation"
|
||||
onDeleted={(deleted: string[]) => {
|
||||
if (selectedItems.length === 0 || selectedItems.length === deleted.length) {
|
||||
const updatedActions = actions.filter(
|
||||
(action) => action.id && !connectorsToDelete.includes(action.id)
|
||||
);
|
||||
setActions(updatedActions);
|
||||
setSelectedItems([]);
|
||||
}
|
||||
setConnectorsToDelete([]);
|
||||
}}
|
||||
onErrors={async () => {
|
||||
// Refresh the actions from the server, some actions may have beend deleted
|
||||
await loadActions();
|
||||
setConnectorsToDelete([]);
|
||||
}}
|
||||
onCancel={async () => {
|
||||
setConnectorsToDelete([]);
|
||||
}}
|
||||
apiDeleteCall={deleteActions}
|
||||
idsToDelete={connectorsToDelete}
|
||||
singleTitle={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.actionsConnectorsList.singleTitle',
|
||||
{ defaultMessage: 'connector' }
|
||||
)}
|
||||
multipleTitle={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.actionsConnectorsList.multipleTitle',
|
||||
{ defaultMessage: 'connectors' }
|
||||
)}
|
||||
showWarningText={showWarningText}
|
||||
warningText={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.actionsConnectorsList.warningText',
|
||||
{
|
||||
defaultMessage:
|
||||
'{connectors, plural, one {This connector is} other {Some connectors are}} currently in use.',
|
||||
values: {
|
||||
connectors: connectorsToDelete.length,
|
||||
},
|
||||
}
|
||||
)}
|
||||
setIsLoadingState={(isLoading: boolean) => setIsLoadingActionTypes(isLoading)}
|
||||
/>
|
||||
<>
|
||||
{actionConnectorTableItems.length !== 0 && (
|
||||
<EuiPageTemplate.Header
|
||||
paddingSize="none"
|
||||
pageTitle={i18n.translate('xpack.triggersActionsUI.connectors.home.appTitle', {
|
||||
defaultMessage: 'Connectors',
|
||||
})}
|
||||
description={i18n.translate('xpack.triggersActionsUI.connectors.home.description', {
|
||||
defaultMessage: 'Connect third-party software with your alerting data.',
|
||||
})}
|
||||
rightSideItems={(canSave
|
||||
? [
|
||||
<EuiButton
|
||||
data-test-subj="createActionButton"
|
||||
key="create-action"
|
||||
fill
|
||||
onClick={() => setAddFlyoutVisibility(true)}
|
||||
iconType="plusInCircle"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.actionsConnectorsList.addActionButtonLabel"
|
||||
defaultMessage="Create connector"
|
||||
/>
|
||||
</EuiButton>,
|
||||
]
|
||||
: []
|
||||
).concat([
|
||||
<EuiButtonEmpty
|
||||
data-test-subj="documentationButton"
|
||||
key="documentation-button"
|
||||
href={docLinks.links.alerting.connectors}
|
||||
iconType="help"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.triggersActionsUI.sections.actionsConnectorsList.documentationButtonLabel"
|
||||
defaultMessage="Documentation"
|
||||
/>
|
||||
</EuiButtonEmpty>,
|
||||
])}
|
||||
/>
|
||||
)}
|
||||
<EuiPageTemplate.Section
|
||||
paddingSize="none"
|
||||
data-test-subj="actionsList"
|
||||
alignment={actionConnectorTableItems.length === 0 ? 'center' : 'top'}
|
||||
>
|
||||
<DeleteModalConfirmation
|
||||
data-test-subj="deleteConnectorsConfirmation"
|
||||
onDeleted={(deleted: string[]) => {
|
||||
if (selectedItems.length === 0 || selectedItems.length === deleted.length) {
|
||||
const updatedActions = actions.filter(
|
||||
(action) => action.id && !connectorsToDelete.includes(action.id)
|
||||
);
|
||||
setActions(updatedActions);
|
||||
setSelectedItems([]);
|
||||
}
|
||||
setConnectorsToDelete([]);
|
||||
}}
|
||||
onErrors={async () => {
|
||||
// Refresh the actions from the server, some actions may have beend deleted
|
||||
await loadActions();
|
||||
setConnectorsToDelete([]);
|
||||
}}
|
||||
onCancel={async () => {
|
||||
setConnectorsToDelete([]);
|
||||
}}
|
||||
apiDeleteCall={deleteActions}
|
||||
idsToDelete={connectorsToDelete}
|
||||
singleTitle={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.actionsConnectorsList.singleTitle',
|
||||
{ defaultMessage: 'connector' }
|
||||
)}
|
||||
multipleTitle={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.actionsConnectorsList.multipleTitle',
|
||||
{ defaultMessage: 'connectors' }
|
||||
)}
|
||||
showWarningText={showWarningText}
|
||||
warningText={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.actionsConnectorsList.warningText',
|
||||
{
|
||||
defaultMessage:
|
||||
'{connectors, plural, one {This connector is} other {Some connectors are}} currently in use.',
|
||||
values: {
|
||||
connectors: connectorsToDelete.length,
|
||||
},
|
||||
}
|
||||
)}
|
||||
setIsLoadingState={(isLoading: boolean) => setIsLoadingActionTypes(isLoading)}
|
||||
/>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
{/* Render the view based on if there's data or if they can save */}
|
||||
{(isLoadingActions || isLoadingActionTypes) && <CenterJustifiedSpinner />}
|
||||
{actionConnectorTableItems.length !== 0 && table}
|
||||
{actionConnectorTableItems.length === 0 &&
|
||||
canSave &&
|
||||
!isLoadingActions &&
|
||||
!isLoadingActionTypes && (
|
||||
<EmptyConnectorsPrompt onCTAClicked={() => setAddFlyoutVisibility(true)} />
|
||||
)}
|
||||
{actionConnectorTableItems.length === 0 && !canSave && <NoPermissionPrompt />}
|
||||
{addFlyoutVisible ? (
|
||||
<CreateConnectorFlyout
|
||||
onClose={() => {
|
||||
setAddFlyoutVisibility(false);
|
||||
}}
|
||||
onTestConnector={(connector) => editItem(connector, EditConnectorTabs.Test)}
|
||||
onConnectorCreated={loadActions}
|
||||
actionTypeRegistry={actionTypeRegistry}
|
||||
/>
|
||||
) : null}
|
||||
{editConnectorProps.initialConnector ? (
|
||||
<EditConnectorFlyout
|
||||
key={`${editConnectorProps.initialConnector.id}${
|
||||
editConnectorProps.tab ? `:${editConnectorProps.tab}` : ``
|
||||
}`}
|
||||
connector={editConnectorProps.initialConnector}
|
||||
tab={editConnectorProps.tab}
|
||||
onClose={() => {
|
||||
setEditConnectorProps(omit(editConnectorProps, 'initialConnector'));
|
||||
}}
|
||||
onConnectorUpdated={(connector) => {
|
||||
setEditConnectorProps({ ...editConnectorProps, initialConnector: connector });
|
||||
loadActions();
|
||||
}}
|
||||
actionTypeRegistry={actionTypeRegistry}
|
||||
/>
|
||||
) : null}
|
||||
</section>
|
||||
<EuiSpacer size="m" />
|
||||
{/* Render the view based on if there's data or if they can save */}
|
||||
{(isLoadingActions || isLoadingActionTypes) && <CenterJustifiedSpinner />}
|
||||
{actionConnectorTableItems.length !== 0 && table}
|
||||
{actionConnectorTableItems.length === 0 &&
|
||||
canSave &&
|
||||
!isLoadingActions &&
|
||||
!isLoadingActionTypes && (
|
||||
<EmptyConnectorsPrompt
|
||||
onCTAClicked={() => setAddFlyoutVisibility(true)}
|
||||
docLinks={docLinks}
|
||||
/>
|
||||
)}
|
||||
{actionConnectorTableItems.length === 0 && !canSave && <NoPermissionPrompt />}
|
||||
{addFlyoutVisible ? (
|
||||
<CreateConnectorFlyout
|
||||
onClose={() => {
|
||||
setAddFlyoutVisibility(false);
|
||||
}}
|
||||
onTestConnector={(connector) => editItem(connector, EditConnectorTabs.Test)}
|
||||
onConnectorCreated={loadActions}
|
||||
actionTypeRegistry={actionTypeRegistry}
|
||||
/>
|
||||
) : null}
|
||||
{editConnectorProps.initialConnector ? (
|
||||
<EditConnectorFlyout
|
||||
key={`${editConnectorProps.initialConnector.id}${
|
||||
editConnectorProps.tab ? `:${editConnectorProps.tab}` : ``
|
||||
}`}
|
||||
connector={editConnectorProps.initialConnector}
|
||||
tab={editConnectorProps.tab}
|
||||
onClose={() => {
|
||||
setEditConnectorProps(omit(editConnectorProps, 'initialConnector'));
|
||||
}}
|
||||
onConnectorUpdated={(connector) => {
|
||||
setEditConnectorProps({ ...editConnectorProps, initialConnector: connector });
|
||||
loadActions();
|
||||
}}
|
||||
actionTypeRegistry={actionTypeRegistry}
|
||||
/>
|
||||
) : null}
|
||||
</EuiPageTemplate.Section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -12,3 +12,4 @@ export { builtInGroupByTypes } from './group_by_types';
|
|||
export const VIEW_LICENSE_OPTIONS_LINK = 'https://www.elastic.co/subscriptions';
|
||||
|
||||
export const PLUGIN_ID = 'triggersActions';
|
||||
export const CONNECTORS_PLUGIN_ID = 'triggersActionsConnectors';
|
||||
|
|
|
@ -69,7 +69,7 @@ import type {
|
|||
} from './types';
|
||||
import { TriggersActionsUiConfigType } from '../common/types';
|
||||
import { registerAlertsTableConfiguration } from './application/sections/alerts_table/alerts_page/register_alerts_table_configuration';
|
||||
import { PLUGIN_ID } from './common/constants';
|
||||
import { PLUGIN_ID, CONNECTORS_PLUGIN_ID } from './common/constants';
|
||||
import type { AlertsTableStateProps } from './application/sections/alerts_table/alerts_table_state';
|
||||
import { getAlertsTableStateLazy } from './common/get_alerts_table_state';
|
||||
import { ActionAccordionFormProps } from './application/sections/action_connector_form/action_form';
|
||||
|
@ -182,12 +182,24 @@ export class Plugin
|
|||
ExperimentalFeaturesService.init({ experimentalFeatures: this.experimentalFeatures });
|
||||
|
||||
const featureTitle = i18n.translate('xpack.triggersActionsUI.managementSection.displayName', {
|
||||
defaultMessage: 'Rules and Connectors',
|
||||
defaultMessage: 'Rules',
|
||||
});
|
||||
const featureDescription = i18n.translate(
|
||||
'xpack.triggersActionsUI.managementSection.displayDescription',
|
||||
{
|
||||
defaultMessage: 'Detect conditions using rules, and take actions using connectors.',
|
||||
defaultMessage: 'Detect conditions using rules.',
|
||||
}
|
||||
);
|
||||
const connectorsFeatureTitle = i18n.translate(
|
||||
'xpack.triggersActionsUI.managementSection.connectors.displayName',
|
||||
{
|
||||
defaultMessage: 'Connectors',
|
||||
}
|
||||
);
|
||||
const connectorsFeatureDescription = i18n.translate(
|
||||
'xpack.triggersActionsUI.managementSection.connectors.displayDescription',
|
||||
{
|
||||
defaultMessage: 'Connect third-party software with your alerting data.',
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -201,6 +213,15 @@ export class Plugin
|
|||
showOnHomePage: false,
|
||||
category: 'admin',
|
||||
});
|
||||
plugins.home.featureCatalogue.register({
|
||||
id: CONNECTORS_PLUGIN_ID,
|
||||
title: connectorsFeatureTitle,
|
||||
description: connectorsFeatureDescription,
|
||||
icon: 'watchesApp',
|
||||
path: '/app/management/insightsAndAlerting/triggersActions',
|
||||
showOnHomePage: false,
|
||||
category: 'admin',
|
||||
});
|
||||
}
|
||||
|
||||
plugins.management.sections.section.insightsAndAlerting.registerApp({
|
||||
|
@ -250,6 +271,53 @@ export class Plugin
|
|||
},
|
||||
});
|
||||
|
||||
plugins.management.sections.section.insightsAndAlerting.registerApp({
|
||||
id: CONNECTORS_PLUGIN_ID,
|
||||
title: connectorsFeatureTitle,
|
||||
order: 2,
|
||||
async mount(params: ManagementAppMountParams) {
|
||||
const [coreStart, pluginsStart] = (await core.getStartServices()) as [
|
||||
CoreStart,
|
||||
PluginsStart,
|
||||
unknown
|
||||
];
|
||||
|
||||
const { renderApp } = await import('./application/connectors_app');
|
||||
|
||||
// The `/api/features` endpoint requires the "Global All" Kibana privilege. Users with a
|
||||
// subset of this privilege are not authorized to access this endpoint and will receive a 404
|
||||
// error that causes the Alerting view to fail to load.
|
||||
let kibanaFeatures: KibanaFeature[];
|
||||
try {
|
||||
kibanaFeatures = await pluginsStart.features.getFeatures();
|
||||
} catch (err) {
|
||||
kibanaFeatures = [];
|
||||
}
|
||||
|
||||
return renderApp({
|
||||
...coreStart,
|
||||
actions: plugins.actions,
|
||||
data: pluginsStart.data,
|
||||
dataViews: pluginsStart.dataViews,
|
||||
dataViewEditor: pluginsStart.dataViewEditor,
|
||||
charts: pluginsStart.charts,
|
||||
alerting: pluginsStart.alerting,
|
||||
spaces: pluginsStart.spaces,
|
||||
unifiedSearch: pluginsStart.unifiedSearch,
|
||||
isCloud: Boolean(plugins.cloud?.isCloudEnabled),
|
||||
element: params.element,
|
||||
theme$: params.theme$,
|
||||
storage: new Storage(window.localStorage),
|
||||
setBreadcrumbs: params.setBreadcrumbs,
|
||||
history: params.history,
|
||||
actionTypeRegistry,
|
||||
ruleTypeRegistry,
|
||||
alertsTableConfigurationRegistry,
|
||||
kibanaFeatures,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
if (this.experimentalFeatures.internalAlertsTable) {
|
||||
registerAlertsTableConfiguration({
|
||||
alertsTableConfigurationRegistry: this.alertsTableConfigurationRegistry,
|
||||
|
|
|
@ -41,7 +41,7 @@ export class WatcherUIPlugin implements Plugin<void, void, Dependencies, any> {
|
|||
const watcherESApp = esSection.registerApp({
|
||||
id: 'watcher',
|
||||
title: pluginName,
|
||||
order: 3,
|
||||
order: 5,
|
||||
mount: async ({ element, setBreadcrumbs, history, theme$ }) => {
|
||||
const [coreStart] = await getStartServices();
|
||||
const {
|
||||
|
|
|
@ -64,7 +64,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
expect(sections).to.have.length(2);
|
||||
expect(sections[0]).to.eql({
|
||||
sectionId: 'insightsAndAlerting',
|
||||
sectionLinks: ['triggersActions', 'cases', 'jobsListLink'],
|
||||
sectionLinks: ['triggersActions', 'cases', 'triggersActionsConnectors', 'jobsListLink'],
|
||||
});
|
||||
expect(sections[1]).to.eql({
|
||||
sectionId: 'kibana',
|
||||
|
|
|
@ -122,7 +122,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
afterEach(async () => {
|
||||
// Reset the Rules tab without reloading the entire page
|
||||
// This is safer than trying to close the alert flyout, which may or may not be open at the end of a test
|
||||
await testSubjects.click('connectorsTab');
|
||||
await testSubjects.click('logsTab');
|
||||
await testSubjects.click('rulesTab');
|
||||
});
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
const retry = getService('retry');
|
||||
const supertest = getService('supertest');
|
||||
const objectRemover = new ObjectRemover(supertest);
|
||||
const browser = getService('browser');
|
||||
|
||||
describe('Connectors', function () {
|
||||
before(async () => {
|
||||
|
@ -26,8 +27,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
.set('kbn-xsrf', 'foo')
|
||||
.send(getTestActionData())
|
||||
.expect(200);
|
||||
await pageObjects.common.navigateToApp('triggersActions');
|
||||
await testSubjects.click('connectorsTab');
|
||||
await pageObjects.common.navigateToApp('triggersActionsConnectors');
|
||||
objectRemover.add(createdAction.id, 'action', 'actions');
|
||||
});
|
||||
|
||||
|
@ -75,6 +75,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
const updatedConnectorName = `${connectorName}updated`;
|
||||
const createdAction = await createConnector(connectorName);
|
||||
objectRemover.add(createdAction.id, 'action', 'actions');
|
||||
await browser.refresh();
|
||||
|
||||
await pageObjects.triggersActionsUI.searchConnectors(connectorName);
|
||||
|
||||
|
@ -112,6 +113,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
const indexName = generateUniqueKey();
|
||||
const createdAction = await createIndexConnector(connectorName, indexName);
|
||||
objectRemover.add(createdAction.id, 'action', 'actions');
|
||||
await browser.refresh();
|
||||
|
||||
await pageObjects.triggersActionsUI.searchConnectors(connectorName);
|
||||
|
||||
|
@ -141,6 +143,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
const indexName = generateUniqueKey();
|
||||
const createdAction = await createIndexConnector(connectorName, indexName);
|
||||
objectRemover.add(createdAction.id, 'action', 'actions');
|
||||
await browser.refresh();
|
||||
|
||||
await pageObjects.triggersActionsUI.searchConnectors(connectorName);
|
||||
|
||||
|
@ -168,6 +171,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
const connectorName = generateUniqueKey();
|
||||
const createdAction = await createConnector(connectorName);
|
||||
objectRemover.add(createdAction.id, 'action', 'actions');
|
||||
await browser.refresh();
|
||||
|
||||
await pageObjects.triggersActionsUI.searchConnectors(connectorName);
|
||||
|
||||
const searchResultsBeforeEdit = await pageObjects.triggersActionsUI.getConnectorsList();
|
||||
|
@ -195,6 +200,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
await createConnector(connectorName);
|
||||
const createdAction = await createConnector(generateUniqueKey());
|
||||
objectRemover.add(createdAction.id, 'action', 'actions');
|
||||
await browser.refresh();
|
||||
|
||||
await pageObjects.triggersActionsUI.searchConnectors(connectorName);
|
||||
|
||||
|
@ -220,6 +226,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
await createConnector(connectorName);
|
||||
const createdAction = await createConnector(generateUniqueKey());
|
||||
objectRemover.add(createdAction.id, 'action', 'actions');
|
||||
await browser.refresh();
|
||||
|
||||
await pageObjects.triggersActionsUI.searchConnectors(connectorName);
|
||||
|
||||
|
@ -285,7 +292,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
connector_type_id: '.slack',
|
||||
})
|
||||
.expect(200);
|
||||
await testSubjects.click('connectorsTab');
|
||||
return createdAction;
|
||||
}
|
||||
|
||||
|
@ -303,7 +309,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
secrets: {},
|
||||
})
|
||||
.expect(200);
|
||||
await testSubjects.click('connectorsTab');
|
||||
return createdAction;
|
||||
}
|
||||
|
||||
|
|
|
@ -437,7 +437,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
await testSubjects.existOrFail('rulesList');
|
||||
|
||||
// delete connector
|
||||
await pageObjects.triggersActionsUI.changeTabs('connectorsTab');
|
||||
await pageObjects.common.navigateToApp('triggersActionsConnectors');
|
||||
await pageObjects.triggersActionsUI.searchConnectors(connector.name);
|
||||
await testSubjects.click('deleteConnector');
|
||||
await testSubjects.existOrFail('deleteIdsConfirmation');
|
||||
|
@ -447,8 +447,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
const toastTitle = await pageObjects.common.closeToast();
|
||||
expect(toastTitle).to.eql('Deleted 1 connector');
|
||||
|
||||
// Wait to ensure the table is finished loading
|
||||
await pageObjects.triggersActionsUI.tableFinishedLoading();
|
||||
|
||||
// click on first alert
|
||||
await pageObjects.triggersActionsUI.changeTabs('rulesTab');
|
||||
await pageObjects.common.navigateToApp('triggersActions');
|
||||
await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(rule.name);
|
||||
|
||||
const editButton = await testSubjects.find('openEditRuleFlyoutButton');
|
||||
|
@ -501,7 +504,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
await testSubjects.existOrFail('rulesList');
|
||||
|
||||
// delete connector
|
||||
await pageObjects.triggersActionsUI.changeTabs('connectorsTab');
|
||||
await pageObjects.common.navigateToApp('triggersActionsConnectors');
|
||||
await pageObjects.triggersActionsUI.searchConnectors(connector.name);
|
||||
await testSubjects.click('deleteConnector');
|
||||
await testSubjects.existOrFail('deleteIdsConfirmation');
|
||||
|
@ -511,8 +514,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
const toastTitle = await pageObjects.common.closeToast();
|
||||
expect(toastTitle).to.eql('Deleted 1 connector');
|
||||
|
||||
// Wait to ensure the table is finished loading
|
||||
await pageObjects.triggersActionsUI.tableFinishedLoading();
|
||||
|
||||
// click on first rule
|
||||
await pageObjects.triggersActionsUI.changeTabs('rulesTab');
|
||||
await pageObjects.common.navigateToApp('triggersActions');
|
||||
await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(alert.name);
|
||||
|
||||
const editButton = await testSubjects.find('openEditRuleFlyoutButton');
|
||||
|
@ -553,7 +559,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
// verify content
|
||||
await testSubjects.existOrFail('rulesList');
|
||||
|
||||
await pageObjects.triggersActionsUI.changeTabs('connectorsTab');
|
||||
await pageObjects.common.navigateToApp('triggersActionsConnectors');
|
||||
await pageObjects.triggersActionsUI.searchConnectors('new connector');
|
||||
await testSubjects.click('deleteConnector');
|
||||
await testSubjects.existOrFail('deleteIdsConfirmation');
|
||||
|
|
|
@ -31,7 +31,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
it('Loads the Alerts page', async () => {
|
||||
await pageObjects.common.navigateToApp('triggersActions');
|
||||
const headingText = await pageObjects.triggersActionsUI.getSectionHeadingText();
|
||||
expect(headingText).to.be('Rules and Connectors');
|
||||
expect(headingText).to.be('Rules');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -45,8 +45,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
|
||||
it('Loads the Alerts page but with error', async () => {
|
||||
await pageObjects.common.navigateToApp('triggersActions');
|
||||
const headingText = await pageObjects.triggersActionsUI.getRulesListTitle();
|
||||
expect(headingText).to.be('No permissions to create rules');
|
||||
const exists = await testSubjects.exists('noPermissionPrompt');
|
||||
expect(exists).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -60,26 +60,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
});
|
||||
|
||||
it('Loads the Alerts page', async () => {
|
||||
await log.debug('Checking for section heading to say Rules and Connectors.');
|
||||
await log.debug('Checking for section heading to say Rules.');
|
||||
|
||||
const headingText = await pageObjects.triggersActionsUI.getSectionHeadingText();
|
||||
expect(headingText).to.be('Rules and Connectors');
|
||||
});
|
||||
|
||||
describe('Connectors tab', () => {
|
||||
it('renders the connectors tab', async () => {
|
||||
// Navigate to the connectors tab
|
||||
await pageObjects.triggersActionsUI.changeTabs('connectorsTab');
|
||||
|
||||
await pageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
// Verify url
|
||||
const url = await browser.getCurrentUrl();
|
||||
expect(url).to.contain(`/connectors`);
|
||||
|
||||
// Verify content
|
||||
await testSubjects.existOrFail('actionsList');
|
||||
});
|
||||
expect(headingText).to.be('Rules');
|
||||
});
|
||||
|
||||
describe('Alerts tab', () => {
|
||||
|
|
|
@ -61,6 +61,9 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
triggersActions: {
|
||||
pathname: '/app/management/insightsAndAlerting/triggersActions',
|
||||
},
|
||||
triggersActionsConnectors: {
|
||||
pathname: '/app/management/insightsAndAlerting/triggersActionsConnectors',
|
||||
},
|
||||
},
|
||||
esTestCluster: {
|
||||
...xpackFunctionalConfig.get('esTestCluster'),
|
||||
|
|
|
@ -61,6 +61,11 @@ export function TriggersActionsPageProvider({ getService }: FtrProviderContext)
|
|||
await this.clickCreateFirstConnectorButton();
|
||||
}
|
||||
},
|
||||
async tableFinishedLoading() {
|
||||
await find.byCssSelector(
|
||||
'.euiBasicTable[data-test-subj="actionsTable"]:not(.euiBasicTable-loading)'
|
||||
);
|
||||
},
|
||||
async searchConnectors(searchText: string) {
|
||||
const searchBox = await find.byCssSelector('[data-test-subj="actionsList"] .euiFieldSearch');
|
||||
await searchBox.click();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue