;
};
}
-
-export const StepDateHistogram = injectI18n(StepDateHistogramUi);
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js
index 4c4019b3161a9..9307c9074e663 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js
@@ -6,7 +6,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
-import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiButtonEmpty,
@@ -20,13 +20,13 @@ import {
EuiTitle,
} from '@elastic/eui';
-import { histogramDetailsUrl } from '../../../services';
+import { getHistogramDetailsUrl } from '../../../services';
import { FieldList } from '../../components';
import { FieldChooser, StepError } from './components';
-export class StepHistogramUi extends Component {
+export class StepHistogram extends Component {
static propTypes = {
fields: PropTypes.object.isRequired,
onFieldsChange: PropTypes.func.isRequired,
@@ -96,7 +96,7 @@ export class StepHistogramUi extends Component {
;
};
}
-
-export const StepHistogram = injectI18n(StepHistogramUi);
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js
index 8cba18804b1c6..024001d463240 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js
@@ -6,7 +6,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
-import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiButtonEmpty,
@@ -26,8 +26,8 @@ import {
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { CronEditor } from '../../../../../../../../../src/plugins/es_ui_shared/public/components/cron_editor';
-import { INDEX_ILLEGAL_CHARACTERS_VISIBLE } from 'ui/indices';
-import { logisticalDetailsUrl, cronUrl } from '../../../services';
+import { INDEX_ILLEGAL_CHARACTERS_VISIBLE } from '../../../../legacy_imports';
+import { getLogisticalDetailsUrl, getCronUrl } from '../../../services';
import { StepError } from './components';
import { indexPatterns } from '../../../../../../../../../src/plugins/data/public';
@@ -35,7 +35,7 @@ import { indexPatterns } from '../../../../../../../../../src/plugins/data/publi
const indexPatternIllegalCharacters = indexPatterns.ILLEGAL_CHARACTERS_VISIBLE.join(' ');
const indexIllegalCharacters = INDEX_ILLEGAL_CHARACTERS_VISIBLE.join(' ');
-export class StepLogisticsUi extends Component {
+export class StepLogistics extends Component {
static propTypes = {
fields: PropTypes.object.isRequired,
onFieldsChange: PropTypes.func.isRequired,
@@ -146,7 +146,7 @@ export class StepLogisticsUi extends Component {
isInvalid={Boolean(areStepErrorsVisible && errorRollupCron)}
helpText={
-
+
;
};
}
-
-export const StepLogistics = injectI18n(StepLogisticsUi);
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js
index 5022754ec5faa..b71b6bfc805bf 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js
@@ -6,7 +6,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
-import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import get from 'lodash/object/get';
@@ -22,7 +22,7 @@ import {
EuiButton,
} from '@elastic/eui';
-import { metricsDetailsUrl } from '../../../services';
+import { getMetricsDetailsUrl } from '../../../services';
import { FieldList } from '../../components';
import { FieldChooser, StepError } from './components';
import { METRICS_CONFIG } from '../../../constants';
@@ -64,7 +64,7 @@ const metricTypesConfig = (function() {
});
})();
-export class StepMetricsUi extends Component {
+export class StepMetrics extends Component {
static propTypes = {
fields: PropTypes.object.isRequired,
onFieldsChange: PropTypes.func.isRequired,
@@ -247,7 +247,7 @@ export class StepMetricsUi extends Component {
}
getListColumns() {
- return StepMetricsUi.chooserColumns.concat({
+ return StepMetrics.chooserColumns.concat({
type: 'metrics',
name: i18n.translate('xpack.rollupJobs.create.stepMetrics.metricsColumnHeader', {
defaultMessage: 'Metrics',
@@ -384,7 +384,7 @@ export class StepMetricsUi extends Component {
}
- columns={StepMetricsUi.chooserColumns}
+ columns={StepMetrics.chooserColumns}
fields={metricsFields}
selectedFields={metrics}
onSelectField={this.onSelectField}
@@ -472,5 +472,3 @@ export class StepMetricsUi extends Component {
},
];
}
-
-export const StepMetrics = injectI18n(StepMetricsUi);
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js
index 19937732275a2..0097792db3105 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js
@@ -6,7 +6,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
-import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@kbn/i18n/react';
import { EuiErrorBoundary, EuiSpacer, EuiTab, EuiTabs, EuiTitle } from '@elastic/eui';
@@ -30,7 +30,7 @@ const JOB_DETAILS_TABS = [
JOB_DETAILS_TAB_REQUEST,
];
-export class StepReviewUi extends Component {
+export class StepReview extends Component {
static propTypes = {
job: PropTypes.object.isRequired,
};
@@ -121,5 +121,3 @@ export class StepReviewUi extends Component {
);
}
}
-
-export const StepReview = injectI18n(StepReviewUi);
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js
index cd3c6cc5127f1..48e045e19f478 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js
@@ -6,7 +6,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
-import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiButtonEmpty,
@@ -17,13 +17,13 @@ import {
EuiTitle,
} from '@elastic/eui';
-import { termsDetailsUrl } from '../../../services';
+import { getTermsDetailsUrl } from '../../../services';
import { FieldList } from '../../components';
import { FieldChooser } from './components';
-export class StepTermsUi extends Component {
+export class StepTerms extends Component {
static propTypes = {
fields: PropTypes.object.isRequired,
onFieldsChange: PropTypes.func.isRequired,
@@ -99,7 +99,7 @@ export class StepTermsUi extends Component {
@@ -251,5 +251,3 @@ export class DetailPanelUi extends Component {
);
}
}
-
-export const DetailPanel = injectI18n(DetailPanelUi);
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.test.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.test.js
index 39153cda1f99d..9ac8e6075e4cf 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.test.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.test.js
@@ -58,12 +58,12 @@ describe('', () => {
});
it("should have children if it's open", () => {
- expect(component.find('DetailPanelUi').children().length).toBeTruthy();
+ expect(component.find('DetailPanel').children().length).toBeTruthy();
});
it('should *not* have children if its closed', () => {
({ component } = initTestBed({ isOpen: false }));
- expect(component.find('DetailPanelUi').children().length).toBeFalsy();
+ expect(component.find('DetailPanel').children().length).toBeFalsy();
});
it('should show a loading when the job is loading', () => {
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.js
index 035a53206c71d..98329a687217a 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.js
@@ -6,9 +6,8 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
-import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
-import chrome from 'ui/chrome';
-import { MANAGEMENT_BREADCRUMB } from 'ui/management';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { i18n } from '@kbn/i18n';
import {
EuiButton,
@@ -26,6 +25,8 @@ import {
EuiCallOut,
} from '@elastic/eui';
+import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public/';
+
import { CRUD_APP_BASE_PATH } from '../../constants';
import { getRouterLinkProps, extractQueryParams, listBreadcrumb } from '../../services';
@@ -67,7 +68,7 @@ export class JobListUi extends Component {
props.loadJobs();
- chrome.breadcrumbs.set([MANAGEMENT_BREADCRUMB, listBreadcrumb]);
+ props.kibana.services.setBreadcrumbs([listBreadcrumb]);
this.state = {};
}
@@ -97,9 +98,7 @@ export class JobListUi extends Component {
}
renderNoPermission() {
- const { intl } = this.props;
- const title = intl.formatMessage({
- id: 'xpack.rollupJobs.jobList.noPermissionTitle',
+ const title = i18n.translate('xpack.rollupJobs.jobList.noPermissionTitle', {
defaultMessage: 'Permission error',
});
return (
@@ -122,13 +121,11 @@ export class JobListUi extends Component {
}
renderError(error) {
- // We can safely depend upon the shape of this error coming from Angular $http, because we
+ // We can safely depend upon the shape of this error coming from http service, because we
// handle unexpected error shapes in the API action.
- const { statusCode, error: errorString } = error.data;
+ const { statusCode, error: errorString } = error.body;
- const { intl } = this.props;
- const title = intl.formatMessage({
- id: 'xpack.rollupJobs.jobList.loadingErrorTitle',
+ const title = i18n.translate('xpack.rollupJobs.jobList.loadingErrorTitle', {
defaultMessage: 'Error loading rollup jobs',
});
return (
@@ -254,4 +251,4 @@ export class JobListUi extends Component {
}
}
-export const JobList = injectI18n(JobListUi);
+export const JobList = withKibana(JobListUi);
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js
index 5c7d53efbd62c..725789fc584de 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js
@@ -4,24 +4,16 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import React from 'react';
import { registerTestBed } from '../../../../../../../test_utils';
import { rollupJobsStore } from '../../store';
import { JobList } from './job_list';
+import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public';
+import { coreMock } from '../../../../../../../../src/core/public/mocks';
+const startMock = coreMock.createStart();
+
jest.mock('ui/new_platform');
-jest.mock('ui/chrome', () => ({
- addBasePath: () => {},
- breadcrumbs: { set: () => {} },
- getInjected: key => {
- if (key === 'uiCapabilities') {
- return {
- navLinks: {},
- management: {},
- catalogue: {},
- };
- }
- },
-}));
jest.mock('../../services', () => {
const services = require.requireActual('../../services');
@@ -40,7 +32,16 @@ const defaultProps = {
isLoading: false,
};
-const initTestBed = registerTestBed(JobList, { defaultProps, store: rollupJobsStore });
+const services = {
+ setBreadcrumbs: startMock.chrome.setBreadcrumbs,
+};
+const Component = props => (
+
+
+
+);
+
+const initTestBed = registerTestBed(Component, { defaultProps, store: rollupJobsStore });
describe('', () => {
it('should render empty prompt when loading is complete and there are no jobs', () => {
@@ -53,21 +54,21 @@ describe('', () => {
const { component, exists } = initTestBed({ isLoading: true });
expect(exists('jobListLoading')).toBeTruthy();
- expect(component.find('JobTableUi').length).toBeFalsy();
+ expect(component.find('JobTable').length).toBeFalsy();
});
it('should display the when there are jobs', () => {
const { component, exists } = initTestBed({ hasJobs: true });
expect(exists('jobListLoading')).toBeFalsy();
- expect(component.find('JobTableUi').length).toBeTruthy();
+ expect(component.find('JobTable').length).toBeTruthy();
});
describe('when there is an API error', () => {
const { exists, find } = initTestBed({
jobLoadError: {
status: 400,
- data: { statusCode: 400, error: 'Houston we got a problem.' },
+ body: { statusCode: 400, error: 'Houston we got a problem.' },
},
});
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js
index 42d48702a3385..4dbe396ab8410 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js
@@ -7,7 +7,7 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { i18n } from '@kbn/i18n';
-import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiCheckbox,
@@ -120,7 +120,7 @@ const COLUMNS = [
},
];
-export class JobTableUi extends Component {
+export class JobTable extends Component {
static propTypes = {
jobs: PropTypes.array,
pager: PropTypes.object.isRequired,
@@ -333,7 +333,7 @@ export class JobTableUi extends Component {
}
render() {
- const { filterChanged, filter, jobs, intl, closeDetailPanel } = this.props;
+ const { filterChanged, filter, jobs, closeDetailPanel } = this.props;
const { idToSelectedJobMap } = this.state;
@@ -360,8 +360,7 @@ export class JobTableUi extends Component {
filterChanged(event.target.value);
}}
data-test-subj="jobTableFilterInput"
- placeholder={intl.formatMessage({
- id: 'xpack.rollupJobs.jobTable.searchInputPlaceholder',
+ placeholder={i18n.translate('xpack.rollupJobs.jobTable.searchInputPlaceholder', {
defaultMessage: 'Search',
})}
aria-label="Search jobs"
@@ -405,5 +404,3 @@ export class JobTableUi extends Component {
);
}
}
-
-export const JobTable = injectI18n(JobTableUi);
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/api.js b/x-pack/legacy/plugins/rollup/public/crud_app/services/api.js
index e712415f9568d..8f95561b72d1d 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/services/api.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/services/api.js
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import chrome from 'ui/chrome';
import {
UIM_JOB_CREATE,
UIM_JOB_DELETE,
@@ -17,39 +16,45 @@ import {
import { getHttp } from './http_provider';
import { trackUserRequest } from './track_ui_metric';
-const apiPrefix = chrome.addBasePath('/api/rollup');
+const apiPrefix = '/api/rollup';
export async function loadJobs() {
- const {
- data: { jobs },
- } = await getHttp().get(`${apiPrefix}/jobs`);
+ const { jobs } = await getHttp().get(`${apiPrefix}/jobs`);
return jobs;
}
export async function startJobs(jobIds) {
const body = { jobIds };
- const request = getHttp().post(`${apiPrefix}/start`, body);
+ const request = getHttp().post(`${apiPrefix}/start`, {
+ body: JSON.stringify(body),
+ });
const actionType = jobIds.length > 1 ? UIM_JOB_START_MANY : UIM_JOB_START;
return await trackUserRequest(request, actionType);
}
export async function stopJobs(jobIds) {
const body = { jobIds };
- const request = getHttp().post(`${apiPrefix}/stop`, body);
+ const request = getHttp().post(`${apiPrefix}/stop`, {
+ body: JSON.stringify(body),
+ });
const actionType = jobIds.length > 1 ? UIM_JOB_STOP_MANY : UIM_JOB_STOP;
return await trackUserRequest(request, actionType);
}
export async function deleteJobs(jobIds) {
const body = { jobIds };
- const request = getHttp().post(`${apiPrefix}/delete`, body);
+ const request = getHttp().post(`${apiPrefix}/delete`, {
+ body: JSON.stringify(body),
+ });
const actionType = jobIds.length > 1 ? UIM_JOB_DELETE_MANY : UIM_JOB_DELETE;
return await trackUserRequest(request, actionType);
}
export async function createJob(job) {
const body = { job };
- const request = getHttp().put(`${apiPrefix}/create`, body);
+ const request = getHttp().put(`${apiPrefix}/create`, {
+ body: JSON.stringify(body),
+ });
return await trackUserRequest(request, UIM_JOB_CREATE);
}
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/api_errors.js b/x-pack/legacy/plugins/rollup/public/crud_app/services/api_errors.ts
similarity index 54%
rename from x-pack/legacy/plugins/rollup/public/crud_app/services/api_errors.js
rename to x-pack/legacy/plugins/rollup/public/crud_app/services/api_errors.ts
index bacaf13405898..af9e1a16e4cc5 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/services/api_errors.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/services/api_errors.ts
@@ -4,12 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { fatalError, toastNotifications } from 'ui/notify';
+import { getNotifications, getFatalErrors } from '../../kibana_services';
-function createToastConfig(error, errorTitle) {
- // Expect an error in the shape provided by Angular's $http service.
- if (error && error.data) {
- const { error: errorString, statusCode, message } = error.data;
+function createToastConfig(error: any, errorTitle: string) {
+ // Expect an error in the shape provided by http service.
+ if (error && error.body) {
+ const { error: errorString, statusCode, message } = error.body;
return {
title: errorTitle,
text: `${statusCode}: ${errorString}. ${message}`,
@@ -17,26 +17,26 @@ function createToastConfig(error, errorTitle) {
}
}
-export function showApiWarning(error, errorTitle) {
+export function showApiWarning(error: any, errorTitle: string) {
const toastConfig = createToastConfig(error, errorTitle);
if (toastConfig) {
- return toastNotifications.addWarning(toastConfig);
+ return getNotifications().toasts.addWarning(toastConfig);
}
// This error isn't an HTTP error, so let the fatal error screen tell the user something
// unexpected happened.
- return fatalError(error, errorTitle);
+ return getFatalErrors().add(error, errorTitle);
}
-export function showApiError(error, errorTitle) {
+export function showApiError(error: any, errorTitle: string) {
const toastConfig = createToastConfig(error, errorTitle);
if (toastConfig) {
- return toastNotifications.addDanger(toastConfig);
+ return getNotifications().toasts.addDanger(toastConfig);
}
// This error isn't an HTTP error, so let the fatal error screen tell the user something
// unexpected happened.
- fatalError(error, errorTitle);
+ getFatalErrors().add(error, errorTitle);
}
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/documentation_links.js b/x-pack/legacy/plugins/rollup/public/crud_app/services/documentation_links.js
index 7616d8bc179c0..ce42b26cc3e86 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/services/documentation_links.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/services/documentation_links.js
@@ -4,16 +4,21 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
+let esBase = '';
+let xPackBase = '';
-const esBase = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}`;
-const xPackBase = `${ELASTIC_WEBSITE_URL}guide/en/x-pack/${DOC_LINK_VERSION}`;
+export function setEsBaseAndXPackBase(elasticWebsiteUrl, docLinksVersion) {
+ esBase = `${elasticWebsiteUrl}guide/en/elasticsearch/reference/${docLinksVersion}`;
+ xPackBase = `${elasticWebsiteUrl}guide/en/x-pack/${docLinksVersion}`;
+}
-export const logisticalDetailsUrl = `${esBase}/rollup-job-config.html#_logistical_details`;
-export const dateHistogramDetailsUrl = `${esBase}/rollup-job-config.html#_date_histogram_2`;
-export const termsDetailsUrl = `${esBase}/rollup-job-config.html#_terms_2`;
-export const histogramDetailsUrl = `${esBase}/rollup-job-config.html#_histogram_2`;
-export const metricsDetailsUrl = `${esBase}/rollup-job-config.html#rollup-metrics-config`;
+export const getLogisticalDetailsUrl = () => `${esBase}/rollup-job-config.html#_logistical_details`;
+export const getDateHistogramDetailsUrl = () =>
+ `${esBase}/rollup-job-config.html#_date_histogram_2`;
+export const getTermsDetailsUrl = () => `${esBase}/rollup-job-config.html#_terms_2`;
+export const getHistogramDetailsUrl = () => `${esBase}/rollup-job-config.html#_histogram_2`;
+export const getMetricsDetailsUrl = () => `${esBase}/rollup-job-config.html#rollup-metrics-config`;
-export const dateHistogramAggregationUrl = `${esBase}/search-aggregations-bucket-datehistogram-aggregation.html`;
-export const cronUrl = `${xPackBase}/trigger-schedule.html#_cron_expressions`;
+export const getDateHistogramAggregationUrl = () =>
+ `${esBase}/search-aggregations-bucket-datehistogram-aggregation.html`;
+export const getCronUrl = () => `${xPackBase}/trigger-schedule.html#_cron_expressions`;
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/http_provider.js b/x-pack/legacy/plugins/rollup/public/crud_app/services/http_provider.ts
similarity index 61%
rename from x-pack/legacy/plugins/rollup/public/crud_app/services/http_provider.js
rename to x-pack/legacy/plugins/rollup/public/crud_app/services/http_provider.ts
index 835a7bdc09d86..dd84328084d05 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/services/http_provider.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/services/http_provider.ts
@@ -4,14 +4,17 @@
* you may not use this file except in compliance with the Elastic License.
*/
-// This is an Angular service, which is why we use this provider pattern to access it within
-// our React app.
-let _http;
+import { HttpStart } from 'src/core/public';
-export function setHttp(http) {
+let _http: HttpStart | null = null;
+
+export function setHttp(http: HttpStart) {
_http = http;
}
export function getHttp() {
+ if (!_http) {
+ throw new Error('Rollup http is not defined');
+ }
return _http;
}
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/index.js b/x-pack/legacy/plugins/rollup/public/crud_app/services/index.js
index 74ed8d8c325c0..790770b9b6a9f 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/services/index.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/services/index.js
@@ -11,13 +11,14 @@ export { showApiError, showApiWarning } from './api_errors';
export { listBreadcrumb, createBreadcrumb } from './breadcrumbs';
export {
- logisticalDetailsUrl,
- dateHistogramDetailsUrl,
- dateHistogramAggregationUrl,
- termsDetailsUrl,
- histogramDetailsUrl,
- metricsDetailsUrl,
- cronUrl,
+ setEsBaseAndXPackBase,
+ getLogisticalDetailsUrl,
+ getDateHistogramDetailsUrl,
+ getDateHistogramAggregationUrl,
+ getTermsDetailsUrl,
+ getHistogramDetailsUrl,
+ getMetricsDetailsUrl,
+ getCronUrl,
} from './documentation_links';
export { filterItems } from './filter_items';
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/create_job.js b/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/create_job.js
index 163860b7f24c6..c85b4c55f665e 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/create_job.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/create_job.js
@@ -5,7 +5,6 @@
*/
import { i18n } from '@kbn/i18n';
-import { fatalError } from 'ui/notify';
import { CRUD_APP_BASE_PATH } from '../../constants';
import {
@@ -24,6 +23,8 @@ import {
CLEAR_CREATE_JOB_ERRORS,
} from '../action_types';
+import { getFatalErrors } from '../../../kibana_services';
+
export const createJob = jobConfig => async dispatch => {
dispatch({
type: CREATE_JOB_START,
@@ -39,12 +40,13 @@ export const createJob = jobConfig => async dispatch => {
]);
} catch (error) {
if (error) {
- const { statusCode, data } = error;
+ const { body } = error;
+ const statusCode = error.statusCode || (body && body.statusCode);
- // Expect an error in the shape provided by Angular's $http service.
- if (data) {
+ // Expect an error in the shape provided by http service.
+ if (body) {
// Some errors have statusCode directly available but some are under a data property.
- if ((statusCode || (data && data.statusCode)) === 409) {
+ if (statusCode === 409) {
return dispatch({
type: CREATE_JOB_FAILURE,
payload: {
@@ -67,9 +69,9 @@ export const createJob = jobConfig => async dispatch => {
error: {
message: i18n.translate('xpack.rollupJobs.createAction.failedDefaultErrorMessage', {
defaultMessage: 'Request failed with a {statusCode} error. {message}',
- values: { statusCode, message: data.message },
+ values: { statusCode, message: body.message },
}),
- cause: data.cause,
+ cause: body.cause,
},
},
});
@@ -78,7 +80,7 @@ export const createJob = jobConfig => async dispatch => {
// This error isn't an HTTP error, so let the fatal error screen tell the user something
// unexpected happened.
- return fatalError(
+ return getFatalErrors().add(
error,
i18n.translate('xpack.rollupJobs.createAction.errorTitle', {
defaultMessage: 'Error creating rollup job',
@@ -86,7 +88,7 @@ export const createJob = jobConfig => async dispatch => {
);
}
- const deserializedJob = deserializeJob(newJob.data);
+ const deserializedJob = deserializeJob(newJob);
dispatch({
type: CREATE_JOB_SUCCESS,
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/delete_jobs.js b/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/delete_jobs.js
index d700ec69839be..0cfc8c24d46e9 100644
--- a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/delete_jobs.js
+++ b/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/delete_jobs.js
@@ -5,7 +5,6 @@
*/
import { i18n } from '@kbn/i18n';
-import { toastNotifications } from 'ui/notify';
import {
deleteJobs as sendDeleteJobsRequest,
@@ -19,6 +18,8 @@ import { UPDATE_JOB_START, UPDATE_JOB_SUCCESS, UPDATE_JOB_FAILURE } from '../act
import { refreshJobs } from './refresh_jobs';
import { closeDetailPanel } from './detail_panel';
+import { getNotifications } from '../../../kibana_services';
+
export const deleteJobs = jobIds => async (dispatch, getState) => {
dispatch({
type: UPDATE_JOB_START,
@@ -40,14 +41,14 @@ export const deleteJobs = jobIds => async (dispatch, getState) => {
}
if (jobIds.length === 1) {
- toastNotifications.addSuccess(
+ getNotifications().toasts.addSuccess(
i18n.translate('xpack.rollupJobs.deleteAction.successSingleNotificationTitle', {
defaultMessage: `Rollup job '{jobId}' was deleted`,
values: { jobId: jobIds[0] },
})
);
} else {
- toastNotifications.addSuccess(
+ getNotifications().toasts.addSuccess(
i18n.translate('xpack.rollupJobs.deleteAction.successMultipleNotificationTitle', {
defaultMessage: '{count} rollup jobs were deleted',
values: { count: jobIds.length },
diff --git a/x-pack/legacy/plugins/rollup/public/extend_index_management/index.js b/x-pack/legacy/plugins/rollup/public/extend_index_management/index.ts
similarity index 76%
rename from x-pack/legacy/plugins/rollup/public/extend_index_management/index.js
rename to x-pack/legacy/plugins/rollup/public/extend_index_management/index.ts
index 5e14d3eabc9a6..1a34811901bbe 100644
--- a/x-pack/legacy/plugins/rollup/public/extend_index_management/index.js
+++ b/x-pack/legacy/plugins/rollup/public/extend_index_management/index.ts
@@ -4,15 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
-import {
- addToggleExtension,
- addBadgeExtension,
-} from '../../../index_management/public/index_management_extensions';
import { get } from 'lodash';
const propertyPath = 'isRollupIndex';
export const rollupToggleExtension = {
- matchIndex: index => {
+ matchIndex: (index: { isRollupIndex: boolean }) => {
return get(index, propertyPath);
},
label: i18n.translate('xpack.rollupJobs.indexMgmtToggle.toggleLabel', {
@@ -20,8 +16,9 @@ export const rollupToggleExtension = {
}),
name: 'rollupToggle',
};
+
export const rollupBadgeExtension = {
- matchIndex: index => {
+ matchIndex: (index: { isRollupIndex: boolean }) => {
return get(index, propertyPath);
},
label: i18n.translate('xpack.rollupJobs.indexMgmtBadge.rollupLabel', {
@@ -30,6 +27,3 @@ export const rollupBadgeExtension = {
color: 'secondary',
filterExpression: 'isRollupIndex:true',
};
-
-addBadgeExtension(rollupBadgeExtension);
-addToggleExtension(rollupToggleExtension);
diff --git a/x-pack/legacy/plugins/rollup/public/index_pattern_creation/index.js b/x-pack/legacy/plugins/rollup/public/index_pattern_creation/index.js
deleted file mode 100644
index 1add469e073bd..0000000000000
--- a/x-pack/legacy/plugins/rollup/public/index_pattern_creation/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import chrome from 'ui/chrome';
-
-import { initIndexPatternCreation } from './register';
-import { CONFIG_ROLLUPS } from '../../common';
-
-const uiSettings = chrome.getUiSettingsClient();
-const isRollupIndexPatternsEnabled = uiSettings.get(CONFIG_ROLLUPS);
-
-if (isRollupIndexPatternsEnabled) {
- initIndexPatternCreation();
-}
diff --git a/x-pack/legacy/plugins/rollup/public/index_pattern_creation/register.js b/x-pack/legacy/plugins/rollup/public/index_pattern_creation/register.js
deleted file mode 100644
index 9a3aed548dcc9..0000000000000
--- a/x-pack/legacy/plugins/rollup/public/index_pattern_creation/register.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { setup as managementSetup } from '../../../../../../src/legacy/core_plugins/management/public/legacy';
-import { RollupIndexPatternCreationConfig } from './rollup_index_pattern_creation_config';
-
-export function initIndexPatternCreation() {
- managementSetup.indexPattern.creation.add(RollupIndexPatternCreationConfig);
-}
diff --git a/x-pack/legacy/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js b/x-pack/legacy/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js
index 07f2a674decc5..82a4c5a888594 100644
--- a/x-pack/legacy/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js
+++ b/x-pack/legacy/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js
@@ -6,10 +6,8 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
-import { npSetup } from 'ui/new_platform';
import { RollupPrompt } from './components/rollup_prompt';
-import { setHttpClient, getRollupIndices } from '../services/api';
import { IndexPatternCreationConfig } from '../../../../../../src/legacy/core_plugins/management/public';
const rollupIndexPatternTypeName = i18n.translate(
@@ -54,7 +52,6 @@ export class RollupIndexPatternCreationConfig extends IndexPatternCreationConfig
...options,
});
- setHttpClient(this.httpClient);
this.rollupIndex = null;
this.rollupJobs = [];
this.rollupIndicesCapabilities = {};
@@ -67,9 +64,10 @@ export class RollupIndexPatternCreationConfig extends IndexPatternCreationConfig
// This is a hack intended to prevent the getRollupIndices() request from being sent if
// we're on /logout. There is a race condition that can arise on that page, whereby this
// request resolves after the logout request resolves, and un-clears the session ID.
- const isAnonymous = npSetup.core.http.anonymousPaths.isAnonymous(window.location.pathname);
+ const isAnonymous = this.httpClient.anonymousPaths.isAnonymous(window.location.pathname);
if (!isAnonymous) {
- this.rollupIndicesCapabilities = await getRollupIndices();
+ const response = await this.httpClient.get('/api/rollup/indices');
+ this.rollupIndicesCapabilities = response || {};
}
this.rollupIndices = Object.keys(this.rollupIndicesCapabilities);
diff --git a/x-pack/legacy/plugins/rollup/public/index_pattern_list/index.js b/x-pack/legacy/plugins/rollup/public/index_pattern_list/index.js
deleted file mode 100644
index 63a3149faaadb..0000000000000
--- a/x-pack/legacy/plugins/rollup/public/index_pattern_list/index.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import chrome from 'ui/chrome';
-import { initIndexPatternList } from './register';
-import { CONFIG_ROLLUPS } from '../../common';
-
-const uiSettings = chrome.getUiSettingsClient();
-const isRollupIndexPatternsEnabled = uiSettings.get(CONFIG_ROLLUPS);
-
-if (isRollupIndexPatternsEnabled) {
- initIndexPatternList();
-}
diff --git a/x-pack/legacy/plugins/rollup/public/index_pattern_list/register.js b/x-pack/legacy/plugins/rollup/public/index_pattern_list/register.js
deleted file mode 100644
index 173c28826436b..0000000000000
--- a/x-pack/legacy/plugins/rollup/public/index_pattern_list/register.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { setup as managementSetup } from '../../../../../../src/legacy/core_plugins/management/public/legacy';
-import { RollupIndexPatternListConfig } from './rollup_index_pattern_list_config';
-
-export function initIndexPatternList() {
- managementSetup.indexPattern.list.add(RollupIndexPatternListConfig);
-}
diff --git a/x-pack/legacy/plugins/rollup/public/kibana_services.ts b/x-pack/legacy/plugins/rollup/public/kibana_services.ts
new file mode 100644
index 0000000000000..335eeb90282ca
--- /dev/null
+++ b/x-pack/legacy/plugins/rollup/public/kibana_services.ts
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { NotificationsStart, FatalErrorsSetup } from 'src/core/public';
+
+let notifications: NotificationsStart | null = null;
+let fatalErrors: FatalErrorsSetup | null = null;
+
+export function getNotifications() {
+ if (!notifications) {
+ throw new Error('Rollup notifications is not defined');
+ }
+ return notifications;
+}
+export function setNotifications(newNotifications: NotificationsStart) {
+ notifications = newNotifications;
+}
+
+export function getFatalErrors() {
+ if (!fatalErrors) {
+ throw new Error('Rollup fatalErrors is not defined');
+ }
+ return fatalErrors;
+}
+export function setFatalErrors(newFatalErrors: FatalErrorsSetup) {
+ fatalErrors = newFatalErrors;
+}
diff --git a/x-pack/legacy/plugins/rollup/public/legacy.ts b/x-pack/legacy/plugins/rollup/public/legacy.ts
new file mode 100644
index 0000000000000..a2738372ff346
--- /dev/null
+++ b/x-pack/legacy/plugins/rollup/public/legacy.ts
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { npSetup, npStart } from 'ui/new_platform';
+import { editorConfigProviders } from 'ui/vis/config';
+import { aggTypeFilters } from 'ui/agg_types/filter';
+import { aggTypeFieldFilters } from 'ui/agg_types/param_types/filter';
+import { addSearchStrategy } from '../../../../../src/plugins/data/public';
+import { RollupPlugin } from './plugin';
+import { setup as management } from '../../../../../src/legacy/core_plugins/management/public/legacy';
+import { addBadgeExtension, addToggleExtension } from '../../index_management/public';
+
+const plugin = new RollupPlugin();
+
+export const setup = plugin.setup(npSetup.core, {
+ ...npSetup.plugins,
+ __LEGACY: {
+ aggTypeFilters,
+ aggTypeFieldFilters,
+ editorConfigProviders,
+ addSearchStrategy,
+ addBadgeExtension,
+ addToggleExtension,
+ managementLegacy: management,
+ },
+});
+export const start = plugin.start(npStart.core);
diff --git a/x-pack/legacy/plugins/rollup/public/legacy_imports.ts b/x-pack/legacy/plugins/rollup/public/legacy_imports.ts
new file mode 100644
index 0000000000000..981f97963591e
--- /dev/null
+++ b/x-pack/legacy/plugins/rollup/public/legacy_imports.ts
@@ -0,0 +1,12 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+// @ts-ignore
+export { findIllegalCharactersInIndexName, INDEX_ILLEGAL_CHARACTERS_VISIBLE } from 'ui/indices';
+
+export { AggTypeFilters } from 'ui/agg_types/filter';
+export { AggTypeFieldFilters } from 'ui/agg_types/param_types/filter';
+export { EditorConfigProviderRegistry } from 'ui/vis/config';
diff --git a/x-pack/legacy/plugins/rollup/public/plugin.ts b/x-pack/legacy/plugins/rollup/public/plugin.ts
new file mode 100644
index 0000000000000..97c03fd1fdfc2
--- /dev/null
+++ b/x-pack/legacy/plugins/rollup/public/plugin.ts
@@ -0,0 +1,128 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { i18n } from '@kbn/i18n';
+import { CoreSetup, CoreStart, Plugin } from 'kibana/public';
+import {
+ EditorConfigProviderRegistry,
+ AggTypeFilters,
+ AggTypeFieldFilters,
+} from './legacy_imports';
+import { SearchStrategyProvider } from '../../../../../src/plugins/data/public';
+import { ManagementSetup as ManagementSetupLegacy } from '../../../../../src/legacy/core_plugins/management/public/np_ready';
+import { rollupBadgeExtension, rollupToggleExtension } from './extend_index_management';
+// @ts-ignore
+import { RollupIndexPatternCreationConfig } from './index_pattern_creation/rollup_index_pattern_creation_config';
+// @ts-ignore
+import { RollupIndexPatternListConfig } from './index_pattern_list/rollup_index_pattern_list_config';
+import { getRollupSearchStrategy } from './search/rollup_search_strategy';
+// @ts-ignore
+import { initAggTypeFilter } from './visualize/agg_type_filter';
+// @ts-ignore
+import { initAggTypeFieldFilter } from './visualize/agg_type_field_filter';
+// @ts-ignore
+import { initEditorConfig } from './visualize/editor_config';
+import { CONFIG_ROLLUPS } from '../common';
+import {
+ FeatureCatalogueCategory,
+ HomePublicPluginSetup,
+} from '../../../../../src/plugins/home/public';
+// @ts-ignore
+import { CRUD_APP_BASE_PATH } from './crud_app/constants';
+import { ManagementSetup } from '../../../../../src/plugins/management/public';
+// @ts-ignore
+import { setEsBaseAndXPackBase, setHttp } from './crud_app/services';
+import { setNotifications, setFatalErrors } from './kibana_services';
+import { renderApp } from './application';
+
+export interface RollupPluginSetupDependencies {
+ __LEGACY: {
+ aggTypeFilters: AggTypeFilters;
+ aggTypeFieldFilters: AggTypeFieldFilters;
+ editorConfigProviders: EditorConfigProviderRegistry;
+ addSearchStrategy: (searchStrategy: SearchStrategyProvider) => void;
+ managementLegacy: ManagementSetupLegacy;
+ addBadgeExtension: (badgeExtension: any) => void;
+ addToggleExtension: (toggleExtension: any) => void;
+ };
+ home?: HomePublicPluginSetup;
+ management: ManagementSetup;
+}
+
+export class RollupPlugin implements Plugin {
+ setup(
+ core: CoreSetup,
+ {
+ __LEGACY: {
+ aggTypeFilters,
+ aggTypeFieldFilters,
+ editorConfigProviders,
+ addSearchStrategy,
+ managementLegacy,
+ addBadgeExtension,
+ addToggleExtension,
+ },
+ home,
+ management,
+ }: RollupPluginSetupDependencies
+ ) {
+ setFatalErrors(core.fatalErrors);
+ addBadgeExtension(rollupBadgeExtension);
+ addToggleExtension(rollupToggleExtension);
+
+ const isRollupIndexPatternsEnabled = core.uiSettings.get(CONFIG_ROLLUPS);
+
+ if (isRollupIndexPatternsEnabled) {
+ managementLegacy.indexPattern.creation.add(RollupIndexPatternCreationConfig);
+ managementLegacy.indexPattern.list.add(RollupIndexPatternListConfig);
+ addSearchStrategy(getRollupSearchStrategy(core.http.fetch));
+ initAggTypeFilter(aggTypeFilters);
+ initAggTypeFieldFilter(aggTypeFieldFilters);
+ initEditorConfig(editorConfigProviders);
+ }
+
+ if (home) {
+ home.featureCatalogue.register({
+ id: 'rollup_jobs',
+ title: 'Rollups',
+ description: i18n.translate('xpack.rollupJobs.featureCatalogueDescription', {
+ defaultMessage:
+ 'Summarize and store historical data in a smaller index for future analysis.',
+ }),
+ icon: 'indexRollupApp',
+ path: `#${CRUD_APP_BASE_PATH}/job_list`,
+ showOnHomePage: true,
+ category: FeatureCatalogueCategory.ADMIN,
+ });
+ }
+
+ const esSection = management.sections.getSection('elasticsearch');
+ if (esSection) {
+ esSection.registerApp({
+ id: 'rollup_jobs',
+ title: i18n.translate('xpack.rollupJobs.appTitle', { defaultMessage: 'Rollup Jobs' }),
+ order: 3,
+ mount(params) {
+ params.setBreadcrumbs([
+ {
+ text: i18n.translate('xpack.rollupJobs.breadcrumbsTitle', {
+ defaultMessage: 'Rollup Jobs',
+ }),
+ },
+ ]);
+
+ return renderApp(core, params);
+ },
+ });
+ }
+ }
+
+ start(core: CoreStart) {
+ setHttp(core.http);
+ setNotifications(core.notifications);
+ setEsBaseAndXPackBase(core.docLinks.ELASTIC_WEBSITE_URL, core.docLinks.DOC_LINK_VERSION);
+ }
+}
diff --git a/x-pack/legacy/plugins/rollup/public/search/index.js b/x-pack/legacy/plugins/rollup/public/search/index.js
deleted file mode 100644
index e76ba4817d72c..0000000000000
--- a/x-pack/legacy/plugins/rollup/public/search/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import chrome from 'ui/chrome';
-
-import { initSearch } from './register';
-import { CONFIG_ROLLUPS } from '../../common';
-
-const uiSettings = chrome.getUiSettingsClient();
-const isRollupIndexPatternsEnabled = uiSettings.get(CONFIG_ROLLUPS);
-
-if (isRollupIndexPatternsEnabled) {
- initSearch();
-}
diff --git a/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.js b/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.ts
similarity index 74%
rename from x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.js
rename to x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.ts
index 18e72cdf0fd3d..4709c0aa498f8 100644
--- a/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.js
+++ b/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.ts
@@ -4,10 +4,17 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { kfetch } from 'ui/kfetch';
-import { SearchError, getSearchErrorType } from '../../../../../../src/plugins/data/public';
+import { HttpSetup } from 'src/core/public';
+import {
+ SearchError,
+ getSearchErrorType,
+ IIndexPattern,
+ SearchStrategyProvider,
+ SearchResponse,
+ SearchRequest,
+} from '../../../../../../src/plugins/data/public';
-function serializeFetchParams(searchRequests) {
+function serializeFetchParams(searchRequests: SearchRequest[]) {
return JSON.stringify(
searchRequests.map(searchRequestWithFetchParams => {
const indexPattern =
@@ -17,7 +24,7 @@ function serializeFetchParams(searchRequests) {
} = searchRequestWithFetchParams;
const query = {
- size: size,
+ size,
aggregations: aggs,
query: _query,
};
@@ -30,7 +37,7 @@ function serializeFetchParams(searchRequests) {
// Rollup search always returns 0 hits, but visualizations expect search responses
// to return hits > 0, otherwise they do not render. We fake the number of hits here
// by counting the number of aggregation buckets/values returned by rollup search.
-function shimHitsInFetchResponse(response) {
+function shimHitsInFetchResponse(response: SearchResponse[]) {
return response.map(result => {
const buckets = result.aggregations
? Object.keys(result.aggregations).reduce((allBuckets, agg) => {
@@ -51,17 +58,16 @@ function shimHitsInFetchResponse(response) {
});
}
-export const rollupSearchStrategy = {
+export const getRollupSearchStrategy = (fetch: HttpSetup['fetch']): SearchStrategyProvider => ({
id: 'rollup',
- search: ({ searchRequests, Promise }) => {
+ search: ({ searchRequests }) => {
// Serialize the fetch params into a format suitable for the body of an ES query.
const serializedFetchParams = serializeFetchParams(searchRequests);
const controller = new AbortController();
- const promise = kfetch({
+ const promise = fetch('../api/rollup/search', {
signal: controller.signal,
- pathname: '../api/rollup/search',
method: 'POST',
body: serializedFetchParams,
});
@@ -69,17 +75,17 @@ export const rollupSearchStrategy = {
return {
searching: promise.then(shimHitsInFetchResponse).catch(error => {
const {
- body: { statusText, error: title, message },
+ body: { statusCode, error: title, message },
res: { url },
} = error;
- // Format kfetch error as a SearchError.
+ // Format fetch error as a SearchError.
const searchError = new SearchError({
- status: statusText,
+ status: statusCode,
title,
message: `Rollup search error: ${message}`,
path: url,
- type: getSearchErrorType({ message }),
+ type: getSearchErrorType({ message }) || '',
});
return Promise.reject(searchError);
@@ -88,11 +94,11 @@ export const rollupSearchStrategy = {
};
},
- isViable: indexPattern => {
+ isViable: (indexPattern: IIndexPattern) => {
if (!indexPattern) {
return false;
}
return indexPattern.type === 'rollup';
},
-};
+});
diff --git a/x-pack/legacy/plugins/rollup/public/services/api.js b/x-pack/legacy/plugins/rollup/public/services/api.js
deleted file mode 100644
index ae9e8756c7efc..0000000000000
--- a/x-pack/legacy/plugins/rollup/public/services/api.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-let httpClient;
-export const setHttpClient = client => {
- httpClient = client;
-};
-
-export async function getRollupIndices() {
- const response = await httpClient.get('/api/rollup/indices');
- return response || {};
-}
diff --git a/x-pack/legacy/plugins/rollup/public/visualize/agg_type_field_filter.js b/x-pack/legacy/plugins/rollup/public/visualize/agg_type_field_filter.js
index 9d19dff648667..6f44e0ef90efd 100644
--- a/x-pack/legacy/plugins/rollup/public/visualize/agg_type_field_filter.js
+++ b/x-pack/legacy/plugins/rollup/public/visualize/agg_type_field_filter.js
@@ -4,9 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { aggTypeFieldFilters } from 'ui/agg_types/param_types/filter';
-
-export function initAggTypeFieldFilter() {
+export function initAggTypeFieldFilter(aggTypeFieldFilters) {
/**
* If rollup index pattern, check its capabilities
* and limit available fields for a given aggType based on that.
diff --git a/x-pack/legacy/plugins/rollup/public/visualize/agg_type_filter.js b/x-pack/legacy/plugins/rollup/public/visualize/agg_type_filter.js
index 75b11dac06cf5..5f9fab3061a19 100644
--- a/x-pack/legacy/plugins/rollup/public/visualize/agg_type_filter.js
+++ b/x-pack/legacy/plugins/rollup/public/visualize/agg_type_filter.js
@@ -4,9 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { aggTypeFilters } from 'ui/agg_types/filter';
-
-export function initAggTypeFilter() {
+export function initAggTypeFilter(aggTypeFilters) {
/**
* If rollup index pattern, check its capabilities
* and limit available aggregations based on that.
diff --git a/x-pack/legacy/plugins/rollup/public/visualize/editor_config.js b/x-pack/legacy/plugins/rollup/public/visualize/editor_config.js
index 897caa07fd873..5c1eb7c8ee3b7 100644
--- a/x-pack/legacy/plugins/rollup/public/visualize/editor_config.js
+++ b/x-pack/legacy/plugins/rollup/public/visualize/editor_config.js
@@ -5,9 +5,8 @@
*/
import { i18n } from '@kbn/i18n';
-import { editorConfigProviders } from 'ui/vis/editors/config/editor_config_providers';
-export function initEditorConfig() {
+export function initEditorConfig(editorConfigProviders) {
// Limit agg params based on rollup capabilities
editorConfigProviders.register((indexPattern, aggConfig) => {
if (indexPattern.type !== 'rollup') {
diff --git a/x-pack/legacy/plugins/rollup/public/visualize/index.js b/x-pack/legacy/plugins/rollup/public/visualize/index.js
deleted file mode 100644
index e5a9c63c91a92..0000000000000
--- a/x-pack/legacy/plugins/rollup/public/visualize/index.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import chrome from 'ui/chrome';
-
-import { initAggTypeFilter } from './agg_type_filter';
-import { initAggTypeFieldFilter } from './agg_type_field_filter';
-import { initEditorConfig } from './editor_config';
-import { CONFIG_ROLLUPS } from '../../common';
-
-const uiSettings = chrome.getUiSettingsClient();
-const isRollupIndexPatternsEnabled = uiSettings.get(CONFIG_ROLLUPS);
-
-if (isRollupIndexPatternsEnabled) {
- initAggTypeFilter();
- initAggTypeFieldFilter();
- initEditorConfig();
-}
diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/navigation/navigation.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/navigation/navigation.spec.ts
index a549b5eec2e7c..364864b395d41 100644
--- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/navigation/navigation.spec.ts
+++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/navigation/navigation.spec.ts
@@ -4,39 +4,32 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { TIMELINES_PAGE } from '../../lib/urls';
-import {
- NAVIGATION_HOSTS,
- NAVIGATION_NETWORK,
- NAVIGATION_OVERVIEW,
- NAVIGATION_TIMELINES,
-} from '../../lib/navigation/selectors';
-import { loginAndWaitForPage } from '../../lib/util/helpers';
+import { TIMELINES_PAGE } from '../../../urls/navigation';
+import { HOSTS, NETWORK, OVERVIEW, TIMELINES } from '../../../screens/header';
+import { loginAndWaitForPage } from '../../../tasks/login';
+import { navigateFromHeaderTo } from '../../../tasks/header';
describe('top-level navigation common to all pages in the SIEM app', () => {
before(() => {
loginAndWaitForPage(TIMELINES_PAGE);
});
it('navigates to the Overview page', () => {
- cy.get(NAVIGATION_OVERVIEW).click({ force: true });
+ navigateFromHeaderTo(OVERVIEW);
cy.url().should('include', '/siem#/overview');
});
it('navigates to the Hosts page', () => {
- cy.get(NAVIGATION_HOSTS).click({ force: true });
-
+ navigateFromHeaderTo(HOSTS);
cy.url().should('include', '/siem#/hosts');
});
it('navigates to the Network page', () => {
- cy.get(NAVIGATION_NETWORK).click({ force: true });
-
+ navigateFromHeaderTo(NETWORK);
cy.url().should('include', '/siem#/network');
});
it('navigates to the Timelines page', () => {
- cy.get(NAVIGATION_TIMELINES).click({ force: true });
-
+ navigateFromHeaderTo(TIMELINES);
cy.url().should('include', '/siem#/timelines');
});
});
diff --git a/x-pack/legacy/plugins/siem/cypress/screens/header.ts b/x-pack/legacy/plugins/siem/cypress/screens/header.ts
index cb018cda8f68d..6e4f5fc0e35cb 100644
--- a/x-pack/legacy/plugins/siem/cypress/screens/header.ts
+++ b/x-pack/legacy/plugins/siem/cypress/screens/header.ts
@@ -5,3 +5,11 @@
*/
export const KQL_INPUT = '[data-test-subj="queryInput"]';
+
+export const HOSTS = '[data-test-subj="navigation-hosts"]';
+
+export const NETWORK = '[data-test-subj="navigation-network"]';
+
+export const OVERVIEW = '[data-test-subj="navigation-overview"]';
+
+export const TIMELINES = '[data-test-subj="navigation-timelines"]';
diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/header.ts b/x-pack/legacy/plugins/siem/cypress/tasks/header.ts
new file mode 100644
index 0000000000000..96412b1eb6a3c
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/cypress/tasks/header.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export const navigateFromHeaderTo = (page: string) => {
+ cy.get(page).click({ force: true });
+};
diff --git a/x-pack/legacy/plugins/ml/server/models/calendar/index.js b/x-pack/legacy/plugins/siem/cypress/urls/navigation.ts
similarity index 81%
rename from x-pack/legacy/plugins/ml/server/models/calendar/index.js
rename to x-pack/legacy/plugins/siem/cypress/urls/navigation.ts
index 11f99bc8fd922..4675829df839a 100644
--- a/x-pack/legacy/plugins/ml/server/models/calendar/index.js
+++ b/x-pack/legacy/plugins/siem/cypress/urls/navigation.ts
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { CalendarManager } from './calendar_manager';
+export const TIMELINES_PAGE = '/app/siem#/timelines';
diff --git a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/default_headers.ts b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/default_headers.ts
index 936d43fff0b48..af9a5ab765571 100644
--- a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/default_headers.ts
+++ b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/default_headers.ts
@@ -19,6 +19,7 @@ export const alertsHeaders: ColumnHeader[] = [
columnHeaderType: defaultColumnHeaderType,
id: 'event.module',
width: DEFAULT_COLUMN_MIN_WIDTH,
+ linkField: 'rule.reference',
},
{
columnHeaderType: defaultColumnHeaderType,
diff --git a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx
index 2d10928da570a..a8c2f429040ea 100644
--- a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx
@@ -5,7 +5,6 @@
*/
import { noop } from 'lodash/fp';
import React, { useEffect, useCallback } from 'react';
-import { EuiSpacer } from '@elastic/eui';
import numeral from '@elastic/numeral';
import { AlertsComponentsQueryProps } from './types';
@@ -79,7 +78,6 @@ export const AlertsView = ({
type={type}
updateDateRange={updateDateRange}
/>
-
>
);
diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/__mocks__/mock.ts b/x-pack/legacy/plugins/siem/public/components/embeddables/__mocks__/mock.ts
index 1f06385e12c94..7834bb4511dc6 100644
--- a/x-pack/legacy/plugins/siem/public/components/embeddables/__mocks__/mock.ts
+++ b/x-pack/legacy/plugins/siem/public/components/embeddables/__mocks__/mock.ts
@@ -51,8 +51,12 @@ export const mockSourceLayer = {
type: 'STATIC',
options: { orientation: 0 },
},
- symbol: {
- options: { symbolizeAs: 'icon', symbolId: 'home' },
+ symbolizeAs: {
+ options: { value: 'icon' },
+ },
+ icon: {
+ type: 'STATIC',
+ options: { value: 'home' },
},
},
},
@@ -103,8 +107,12 @@ export const mockDestinationLayer = {
type: 'STATIC',
options: { orientation: 0 },
},
- symbol: {
- options: { symbolizeAs: 'icon', symbolId: 'marker' },
+ symbolizeAs: {
+ options: { value: 'icon' },
+ },
+ icon: {
+ type: 'STATIC',
+ options: { value: 'marker' },
},
},
},
@@ -154,8 +162,12 @@ export const mockClientLayer = {
type: 'STATIC',
options: { orientation: 0 },
},
- symbol: {
- options: { symbolizeAs: 'icon', symbolId: 'home' },
+ symbolizeAs: {
+ options: { value: 'icon' },
+ },
+ icon: {
+ type: 'STATIC',
+ options: { value: 'home' },
},
},
},
@@ -206,8 +218,12 @@ export const mockServerLayer = {
type: 'STATIC',
options: { orientation: 0 },
},
- symbol: {
- options: { symbolizeAs: 'icon', symbolId: 'marker' },
+ symbolizeAs: {
+ options: { value: 'icon' },
+ },
+ icon: {
+ type: 'STATIC',
+ options: { value: 'marker' },
},
},
},
@@ -266,8 +282,12 @@ export const mockLineLayer = {
type: 'STATIC',
options: { orientation: 0 },
},
- symbol: {
- options: { symbolizeAs: 'circle', symbolId: 'airfield' },
+ symbolizeAs: {
+ options: { value: 'icon' },
+ },
+ icon: {
+ type: 'STATIC',
+ options: { value: 'airfield' },
},
},
},
@@ -326,8 +346,12 @@ export const mockClientServerLineLayer = {
type: 'STATIC',
options: { orientation: 0 },
},
- symbol: {
- options: { symbolizeAs: 'circle', symbolId: 'airfield' },
+ symbolizeAs: {
+ options: { value: 'icon' },
+ },
+ icon: {
+ type: 'STATIC',
+ options: { value: 'airfield' },
},
},
},
diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap
index 2eefdf767dce1..171926b53e5b9 100644
--- a/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap
+++ b/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap
@@ -16,7 +16,7 @@ exports[`IndexPatternsMissingPrompt renders correctly against snapshot 1`] = `
{
<>
{
return (
-
+
);
};
diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx
index f8853deeaed52..04b988f8270f3 100644
--- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx
@@ -6,8 +6,9 @@
import React, { useState, useEffect, useCallback } from 'react';
import { ScaleType } from '@elastic/charts';
+import styled from 'styled-components';
-import { EuiFlexGroup, EuiFlexItem, EuiProgress, EuiSelect } from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem, EuiProgress, EuiSelect, EuiSpacer } from '@elastic/eui';
import { noop } from 'lodash/fp';
import * as i18n from './translations';
import { BarChart } from '../charts/barchart';
@@ -25,8 +26,21 @@ import {
import { ChartSeriesData } from '../charts/common';
import { InspectButtonContainer } from '../inspect';
+const DEFAULT_PANEL_HEIGHT = 300;
+
+const HeaderChildrenFlexItem = styled(EuiFlexItem)`
+ margin-left: 24px;
+`;
+
+const HistogramPanel = styled(Panel)<{ height?: number }>`
+ display: flex;
+ flex-direction: column;
+ ${({ height }) => (height != null ? `height: ${height}px;` : '')}
+`;
+
export const MatrixHistogramComponent: React.FC = ({
+ chartHeight,
dataKey,
defaultStackByOption,
endDate,
@@ -43,6 +57,7 @@ export const MatrixHistogramComponent: React.FC {
const barchartConfigs = getBarchartConfigs({
+ chartHeight,
from: startDate,
legendPosition,
to: endDate,
@@ -141,48 +157,69 @@ export const MatrixHistogramComponent: React.FC
-
- {loading && !isInitialLoading && (
-
- )}
-
- {isInitialLoading ? (
- <>
-
-
- >
- ) : (
- <>
- = 0 ? subtitleWithCounts : null)}
- >
-
-
- {stackByOptions?.length > 1 && (
-
- )}
-
- {headerChildren}
-
-
-
- >
- )}
-
-
+ <>
+
+
+ {loading && !isInitialLoading && (
+
+ )}
+
+ {isInitialLoading ? (
+ <>
+ = 0 ? subtitleWithCounts : null)}
+ >
+
+
+ {stackByOptions?.length > 1 && (
+
+ )}
+
+ {headerChildren}
+
+
+
+ >
+ ) : (
+ <>
+ = 0 ? subtitleWithCounts : null)}
+ >
+
+
+ {stackByOptions?.length > 1 && (
+
+ )}
+
+ {headerChildren}
+
+
+
+ >
+ )}
+
+
+
+ >
);
};
diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/matrix_loader.tsx b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/matrix_loader.tsx
index 769ef170898b0..036526a14f77d 100644
--- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/matrix_loader.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/matrix_loader.tsx
@@ -9,7 +9,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
import styled from 'styled-components';
const StyledEuiFlexGroup = styled(EuiFlexGroup)`
- height: 350px; /* to avoid jump when histogram loads */
+ flex 1;
`;
const MatrixLoaderComponent = () => (
diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/types.ts b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/types.ts
index e2b5600d539af..88f8f1ff28fa9 100644
--- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/types.ts
+++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/types.ts
@@ -31,6 +31,7 @@ export type GetSubTitle = (count: number) => string;
export type GetTitle = (matrixHistogramOption: MatrixHistogramOption) => string;
export interface MatrixHistogramBasicProps {
+ chartHeight?: number;
defaultIndex: string[];
defaultStackByOption: MatrixHistogramOption;
endDate: number;
@@ -39,6 +40,7 @@ export interface MatrixHistogramBasicProps {
id: string;
legendPosition?: Position;
mapping?: MatrixHistogramMappingTypes;
+ panelHeight?: number;
setQuery: SetQuery;
sourceId: string;
startDate: number;
diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts
index 6e932f0c87347..95b1cd806cf6c 100644
--- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts
+++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts
@@ -11,6 +11,7 @@ import { MatrixHistogramDataTypes, MatrixHistogramMappingTypes } from './types';
import { histogramDateTimeFormatter } from '../utils';
interface GetBarchartConfigsProps {
+ chartHeight?: number;
from: number;
legendPosition?: Position;
to: number;
@@ -20,7 +21,10 @@ interface GetBarchartConfigsProps {
showLegend?: boolean;
}
+export const DEFAULT_CHART_HEIGHT = 174;
+
export const getBarchartConfigs = ({
+ chartHeight,
from,
legendPosition,
to,
@@ -65,7 +69,7 @@ export const getBarchartConfigs = ({
},
},
},
- customHeight: 324,
+ customHeight: chartHeight ?? DEFAULT_CHART_HEIGHT,
});
export const formatToChartDataItem = ([key, value]: [
diff --git a/x-pack/legacy/plugins/siem/public/components/news_feed/index.tsx b/x-pack/legacy/plugins/siem/public/components/news_feed/index.tsx
index 95f12758d5e63..6a5e08b287f96 100644
--- a/x-pack/legacy/plugins/siem/public/components/news_feed/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/news_feed/index.tsx
@@ -8,7 +8,7 @@ import React, { useEffect, useState } from 'react';
import chrome from 'ui/chrome';
import { fetchNews, getNewsFeedUrl, getNewsItemsFromApiResponse } from './helpers';
-import { useUiSetting$ } from '../../lib/kibana';
+import { useKibana, useUiSetting$ } from '../../lib/kibana';
import { NewsFeed } from './news_feed';
import { NewsItem } from './types';
@@ -16,10 +16,14 @@ export const StatefulNewsFeed = React.memo<{
enableNewsFeedSetting: string;
newsFeedSetting: string;
}>(({ enableNewsFeedSetting, newsFeedSetting }) => {
+ const kibanaNewsfeedEnabled = useKibana().services.newsfeed;
const [enableNewsFeed] = useUiSetting$(enableNewsFeedSetting);
const [newsFeedUrlSetting] = useUiSetting$(newsFeedSetting);
const [news, setNews] = useState(null);
+ // respect kibana's global newsfeed.enabled setting
+ const newsfeedEnabled = kibanaNewsfeedEnabled && enableNewsFeed;
+
const newsFeedUrl = getNewsFeedUrl({
newsFeedUrlSetting,
getKibanaVersion: chrome.getKibanaVersion,
@@ -42,16 +46,16 @@ export const StatefulNewsFeed = React.memo<{
}
};
- if (enableNewsFeed) {
+ if (newsfeedEnabled) {
fetchData();
}
return () => {
canceled = true;
};
- }, [enableNewsFeed, newsFeedUrl]);
+ }, [newsfeedEnabled, newsFeedUrl]);
- return <>{enableNewsFeed ? : null}>;
+ return <>{newsfeedEnabled ? : null}>;
});
StatefulNewsFeed.displayName = 'StatefulNewsFeed';
diff --git a/x-pack/legacy/plugins/siem/public/components/news_feed/news_feed.tsx b/x-pack/legacy/plugins/siem/public/components/news_feed/news_feed.tsx
index d41ce357d9b7b..98eea1eaa6454 100644
--- a/x-pack/legacy/plugins/siem/public/components/news_feed/news_feed.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/news_feed/news_feed.tsx
@@ -4,39 +4,42 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiLoadingSpinner, EuiSpacer } from '@elastic/eui';
+import { EuiSpacer } from '@elastic/eui';
import React from 'react';
-import { NoNews } from './no_news';
+import { LoadingPlaceholders } from '../page/overview/loading_placeholders';
import { NEWS_FEED_TITLE } from '../../pages/overview/translations';
-import { Post } from './post';
import { SidebarHeader } from '../sidebar_header';
+
+import { NoNews } from './no_news';
+import { Post } from './post';
import { NewsItem } from './types';
interface Props {
news: NewsItem[] | null | undefined;
}
-export const NewsFeed = React.memo(({ news }) => {
- if (news == null) {
- return ;
- }
-
- if (news.length === 0) {
- return ;
- }
+const SHOW_PLACEHOLDERS = 5;
+const LINES_PER_LOADING_PLACEHOLDER = 4;
- return (
- <>
-
- {news.map((n: NewsItem) => (
+const NewsFeedComponent: React.FC = ({ news }) => (
+ <>
+
+ {news == null ? (
+
+ ) : news.length === 0 ? (
+
+ ) : (
+ news.map((n: NewsItem) => (
- ))}
- >
- );
-});
+ ))
+ )}
+ >
+);
+
+NewsFeedComponent.displayName = 'NewsFeedComponent';
-NewsFeed.displayName = 'NewsFeed';
+export const NewsFeed = React.memo(NewsFeedComponent);
diff --git a/x-pack/legacy/plugins/siem/public/components/news_feed/no_news/index.tsx b/x-pack/legacy/plugins/siem/public/components/news_feed/no_news/index.tsx
index bd6648025d2aa..c4e0482c6b30a 100644
--- a/x-pack/legacy/plugins/siem/public/components/news_feed/no_news/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/news_feed/no_news/index.tsx
@@ -12,7 +12,7 @@ import * as i18n from '../translations';
export const NoNews = React.memo(() => (
<>
- {i18n.NO_NEWS_MESSAGE}
+ {i18n.NO_NEWS_MESSAGE}{' '}
{i18n.ADVANCED_SETTINGS_LINK_TITLE}
diff --git a/x-pack/legacy/plugins/siem/public/components/news_feed/translations.ts b/x-pack/legacy/plugins/siem/public/components/news_feed/translations.ts
index 71981723cc937..5d3b4171f501e 100644
--- a/x-pack/legacy/plugins/siem/public/components/news_feed/translations.ts
+++ b/x-pack/legacy/plugins/siem/public/components/news_feed/translations.ts
@@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n';
export const NO_NEWS_MESSAGE = i18n.translate('xpack.siem.newsFeed.noNewsMessage', {
defaultMessage:
- 'Your current News feed URL returned no recent news. You may update the URL or disable security news via',
+ 'Your current news feed URL returned no recent news. You may update the URL or disable security news via',
});
export const ADVANCED_SETTINGS_LINK_TITLE = i18n.translate(
diff --git a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.ts b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.ts
index bd0859bac2d13..6fb53d67c1a6d 100644
--- a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.ts
+++ b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.ts
@@ -4,8 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export const createFilter = (key: string, value: string | null | undefined) =>
- value != null
+import { esFilters } from '../../../../../../../../src/plugins/data/public';
+
+export const createFilter = (
+ key: string,
+ value: string[] | string | null | undefined
+): esFilters.Filter => {
+ const queryValue = value != null ? (Array.isArray(value) ? value[0] : value) : null;
+ return queryValue != null
? {
meta: {
alias: null,
@@ -13,21 +19,21 @@ export const createFilter = (key: string, value: string | null | undefined) =>
disabled: false,
type: 'phrase',
key,
- value,
+ value: queryValue,
params: {
- query: value,
+ query: queryValue,
},
},
query: {
match: {
[key]: {
- query: value,
+ query: queryValue,
type: 'phrase',
},
},
},
}
- : {
+ : ({
exists: {
field: key,
},
@@ -39,4 +45,5 @@ export const createFilter = (key: string, value: string | null | undefined) =>
type: 'exists',
value: 'exists',
},
- };
+ } as esFilters.Filter);
+};
diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/loading_placeholders/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/overview/loading_placeholders/index.tsx
new file mode 100644
index 0000000000000..1dcc6b75f32e5
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/page/overview/loading_placeholders/index.tsx
@@ -0,0 +1,26 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EuiLoadingContent, EuiSpacer } from '@elastic/eui';
+import React from 'react';
+
+const LoadingPlaceholdersComponent: React.FC<{
+ lines: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
+ placeholders: number;
+}> = ({ lines, placeholders }) => (
+ <>
+ {[...Array(placeholders).keys()].map((_, i) => (
+
+
+ {i !== placeholders - 1 && }
+
+ ))}
+ >
+);
+
+LoadingPlaceholdersComponent.displayName = 'LoadingPlaceholdersComponent';
+
+export const LoadingPlaceholders = React.memo(LoadingPlaceholdersComponent);
diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.test.tsx
new file mode 100644
index 0000000000000..568cf032fb01c
--- /dev/null
+++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.test.tsx
@@ -0,0 +1,144 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { cloneDeep } from 'lodash/fp';
+import { mount } from 'enzyme';
+import React from 'react';
+
+import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../../mock';
+
+import { OverviewHost } from '.';
+import { createStore, State } from '../../../../store';
+import { overviewHostQuery } from '../../../../containers/overview/overview_host/index.gql_query';
+import { GetOverviewHostQuery } from '../../../../graphql/types';
+import { MockedProvider } from 'react-apollo/test-utils';
+import { wait } from '../../../../lib/helpers';
+
+jest.mock('../../../../lib/kibana');
+
+const startDate = 1579553397080;
+const endDate = 1579639797080;
+
+interface MockedProvidedQuery {
+ request: {
+ query: GetOverviewHostQuery.Query;
+ fetchPolicy: string;
+ variables: GetOverviewHostQuery.Variables;
+ };
+ result: {
+ data: {
+ source: unknown;
+ };
+ };
+}
+
+const mockOpenTimelineQueryResults: MockedProvidedQuery[] = [
+ {
+ request: {
+ query: overviewHostQuery,
+ fetchPolicy: 'cache-and-network',
+ variables: {
+ sourceId: 'default',
+ timerange: { interval: '12h', from: startDate, to: endDate },
+ filterQuery: undefined,
+ defaultIndex: [
+ 'apm-*-transaction*',
+ 'auditbeat-*',
+ 'endgame-*',
+ 'filebeat-*',
+ 'packetbeat-*',
+ 'winlogbeat-*',
+ ],
+ inspect: false,
+ },
+ },
+ result: {
+ data: {
+ source: {
+ id: 'default',
+ OverviewHost: {
+ auditbeatAuditd: 1,
+ auditbeatFIM: 1,
+ auditbeatLogin: 1,
+ auditbeatPackage: 1,
+ auditbeatProcess: 1,
+ auditbeatUser: 1,
+ endgameDns: 1,
+ endgameFile: 1,
+ endgameImageLoad: 1,
+ endgameNetwork: 1,
+ endgameProcess: 1,
+ endgameRegistry: 1,
+ endgameSecurity: 1,
+ filebeatSystemModule: 1,
+ winlogbeatSecurity: 1,
+ winlogbeatMWSysmonOperational: 1,
+ },
+ },
+ },
+ },
+ },
+];
+
+describe('OverviewHost', () => {
+ const state: State = mockGlobalState;
+
+ let store = createStore(state, apolloClientObservable);
+
+ beforeEach(() => {
+ const myState = cloneDeep(state);
+ store = createStore(myState, apolloClientObservable);
+ });
+
+ test('it renders the expected widget title', () => {
+ const wrapper = mount(
+
+
+
+ );
+
+ expect(
+ wrapper
+ .find('[data-test-subj="header-section-title"]')
+ .first()
+ .text()
+ ).toEqual('Host events');
+ });
+
+ test('it renders an empty subtitle while loading', () => {
+ const wrapper = mount(
+
+
+
+ );
+
+ expect(
+ wrapper
+ .find('[data-test-subj="header-panel-subtitle"]')
+ .first()
+ .text()
+ ).toEqual('');
+ });
+
+ test('it renders the expected event count in the subtitle after loading events', async () => {
+ const wrapper = mount(
+
+
+
+
+
+ );
+ await wait();
+ wrapper.update();
+
+ expect(
+ wrapper
+ .find('[data-test-subj="header-panel-subtitle"]')
+ .first()
+ .text()
+ ).toEqual('Showing: 16 events');
+ });
+});
diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx
index 31d8467025f96..3868885fa29ee 100644
--- a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_host/index.tsx
@@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { isEmpty } from 'lodash/fp';
import { EuiButton, EuiFlexItem, EuiPanel } from '@elastic/eui';
import numeral from '@elastic/numeral';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -41,7 +42,7 @@ export interface OwnProps {
}
const OverviewHostStatsManage = manageQuery(OverviewHostStats);
-type OverviewHostProps = OwnProps;
+export type OverviewHostProps = OwnProps;
const OverviewHostComponent: React.FC = ({
endDate,
@@ -56,6 +57,7 @@ const OverviewHostComponent: React.FC = ({
= ({
return (
<>
+ !isEmpty(overviewHost) ? (
+
+ ) : (
+ <>{''}>
+ )
}
title={
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-