From b1a39ce23cdf819011507ba3dfe696973097b415 Mon Sep 17 00:00:00 2001
From: Xavier Mouligneau <189600+XavierM@users.noreply.github.com>
Date: Wed, 1 Apr 2020 16:33:51 -0400
Subject: [PATCH 01/99] [SIEM] CASES Bugs BC2 (#62170)
* fix persistence between filter
* Fix API filtering bug
* Show username if full name is empty
* fix user in avatar
* do not allow push to service now when connector is none
* fix types
* Show errors from actions
* update connector name in configure
Co-authored-by: Christos Nasikas
---
.../siem/public/containers/case/api.ts | 7 ++++++
.../case/configure/use_configure.tsx | 23 +++++++++++--------
.../public/containers/case/translations.ts | 7 ++++++
.../public/containers/case/use_get_cases.tsx | 15 +++++++-----
.../case/components/all_cases/columns.tsx | 2 +-
.../pages/case/components/all_cases/index.tsx | 6 ++---
.../components/use_push_to_service/index.tsx | 6 ++++-
.../user_action_tree/user_action_item.tsx | 4 ++--
.../server/routes/api/cases/find_cases.ts | 5 ++--
9 files changed, 51 insertions(+), 24 deletions(-)
diff --git a/x-pack/legacy/plugins/siem/public/containers/case/api.ts b/x-pack/legacy/plugins/siem/public/containers/case/api.ts
index bd243d0ba5f64..69e1602b3d981 100644
--- a/x-pack/legacy/plugins/siem/public/containers/case/api.ts
+++ b/x-pack/legacy/plugins/siem/public/containers/case/api.ts
@@ -47,6 +47,8 @@ import {
decodeServiceConnectorCaseResponse,
} from './utils';
+import * as i18n from './translations';
+
export const getCase = async (
caseId: string,
includeComments: boolean = true,
@@ -240,6 +242,11 @@ export const pushToService = async (
signal,
}
);
+
+ if (response.status === 'error') {
+ throw new Error(response.serviceMessage ?? response.message ?? i18n.ERROR_PUSH_TO_SERVICE);
+ }
+
return decodeServiceConnectorCaseResponse(response.data);
};
diff --git a/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx
index 6524c40a8e6e4..19d80bba1e0f8 100644
--- a/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx
+++ b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx
@@ -21,7 +21,11 @@ interface PersistCaseConfigure {
export interface ReturnUseCaseConfigure {
loading: boolean;
refetchCaseConfigure: () => void;
- persistCaseConfigure: ({ connectorId, closureType }: PersistCaseConfigure) => unknown;
+ persistCaseConfigure: ({
+ connectorId,
+ connectorName,
+ closureType,
+ }: PersistCaseConfigure) => unknown;
persistLoading: boolean;
}
@@ -97,19 +101,20 @@ export const useCaseConfigure = ({
const saveCaseConfiguration = async () => {
try {
setPersistLoading(true);
+ const connectorObj = {
+ connector_id: connectorId,
+ connector_name: connectorName,
+ closure_type: closureType,
+ };
const res =
version.length === 0
- ? await postCaseConfigure(
+ ? await postCaseConfigure(connectorObj, abortCtrl.signal)
+ : await patchCaseConfigure(
{
- connector_id: connectorId,
- connector_name: connectorName,
- closure_type: closureType,
+ ...connectorObj,
+ version,
},
abortCtrl.signal
- )
- : await patchCaseConfigure(
- { connector_id: connectorId, closure_type: closureType, version },
- abortCtrl.signal
);
if (!didCancel) {
setPersistLoading(false);
diff --git a/x-pack/legacy/plugins/siem/public/containers/case/translations.ts b/x-pack/legacy/plugins/siem/public/containers/case/translations.ts
index a453be32480e2..d5ea287fd2cdd 100644
--- a/x-pack/legacy/plugins/siem/public/containers/case/translations.ts
+++ b/x-pack/legacy/plugins/siem/public/containers/case/translations.ts
@@ -63,3 +63,10 @@ export const SUCCESS_SEND_TO_EXTERNAL_SERVICE = i18n.translate(
defaultMessage: 'Successfully sent to ServiceNow',
}
);
+
+export const ERROR_PUSH_TO_SERVICE = i18n.translate(
+ 'xpack.siem.case.configure.errorPushingToService',
+ {
+ defaultMessage: 'Error pushing to service',
+ }
+);
diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx
index 323dc23e1b24e..1cbce5af6304b 100644
--- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx
+++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx
@@ -35,7 +35,7 @@ export type Action =
}
| { type: 'FETCH_FAILURE'; payload: string }
| { type: 'FETCH_UPDATE_CASE_SUCCESS' }
- | { type: 'UPDATE_FILTER_OPTIONS'; payload: FilterOptions }
+ | { type: 'UPDATE_FILTER_OPTIONS'; payload: Partial }
| { type: 'UPDATE_QUERY_PARAMS'; payload: Partial }
| { type: 'UPDATE_TABLE_SELECTIONS'; payload: Case[] };
@@ -68,7 +68,10 @@ const dataFetchReducer = (state: UseGetCasesState, action: Action): UseGetCasesS
case 'UPDATE_FILTER_OPTIONS':
return {
...state,
- filterOptions: action.payload,
+ filterOptions: {
+ ...state.filterOptions,
+ ...action.payload,
+ },
};
case 'UPDATE_QUERY_PARAMS':
return {
@@ -119,8 +122,8 @@ interface UseGetCases extends UseGetCasesState {
refetchCasesStatus,
}: UpdateCase) => void;
refetchCases: (filters: FilterOptions, queryParams: QueryParams) => void;
- setFilters: (filters: FilterOptions) => void;
- setQueryParams: (queryParams: QueryParams) => void;
+ setFilters: (filters: Partial) => void;
+ setQueryParams: (queryParams: Partial) => void;
setSelectedCases: (mySelectedCases: Case[]) => void;
}
@@ -139,11 +142,11 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => {
dispatch({ type: 'UPDATE_TABLE_SELECTIONS', payload: mySelectedCases });
}, []);
- const setQueryParams = useCallback((newQueryParams: QueryParams) => {
+ const setQueryParams = useCallback((newQueryParams: Partial) => {
dispatch({ type: 'UPDATE_QUERY_PARAMS', payload: newQueryParams });
}, []);
- const setFilters = useCallback((newFilters: FilterOptions) => {
+ const setFilters = useCallback((newFilters: Partial) => {
dispatch({ type: 'UPDATE_FILTER_OPTIONS', payload: newFilters });
}, []);
diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx
index f757fd33a93a8..0e12f78e29bc2 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx
@@ -77,7 +77,7 @@ export const getCasesColumns = (
size="s"
/>
- {createdBy.fullName ?? createdBy.username ?? ''}
+ {createdBy.fullName ? createdBy.fullName : createdBy.username ?? ''}
>
);
diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx
index 161910bb5498a..b0ff3dbada6c9 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx
@@ -254,11 +254,11 @@ export const AllCases = React.memo(({ userCanCrud }) => {
const onFilterChangedCallback = useCallback(
(newFilterOptions: Partial) => {
if (newFilterOptions.status && newFilterOptions.status === 'closed') {
- setQueryParams({ ...queryParams, sortField: SortFieldCase.closedAt });
+ setQueryParams({ sortField: SortFieldCase.closedAt });
} else if (newFilterOptions.status && newFilterOptions.status === 'open') {
- setQueryParams({ ...queryParams, sortField: SortFieldCase.createdAt });
+ setQueryParams({ sortField: SortFieldCase.createdAt });
}
- setFilters({ ...filterOptions, ...newFilterOptions });
+ setFilters(newFilterOptions);
},
[filterOptions, queryParams]
);
diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.tsx
index aeb694e52b7fa..4f370ec978906 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.tsx
@@ -74,7 +74,11 @@ export const usePushToService = ({
if (actionLicense != null && !actionLicense.enabledInLicense) {
errors = [...errors, getLicenseError()];
}
- if (connector == null && !loadingCaseConfigure && !loadingLicense) {
+ if (
+ (connector == null || (connector != null && connector.connectorId === 'none')) &&
+ !loadingCaseConfigure &&
+ !loadingLicense
+ ) {
errors = [
...errors,
{
diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx
index 89b94d98f91db..bcb4edd6129a6 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx
@@ -134,8 +134,8 @@ export const UserActionItem = ({
- {(fullName && fullName.length > 0) || username.length > 0 ? (
-
+ {(fullName && fullName.length > 0) || (username && username.length > 0) ? (
+ 0 ? fullName : username ?? ''} />
) : (
)}
diff --git a/x-pack/plugins/case/server/routes/api/cases/find_cases.ts b/x-pack/plugins/case/server/routes/api/cases/find_cases.ts
index e7b2044f2badf..b2716749e9749 100644
--- a/x-pack/plugins/case/server/routes/api/cases/find_cases.ts
+++ b/x-pack/plugins/case/server/routes/api/cases/find_cases.ts
@@ -31,9 +31,10 @@ const buildFilter = (
): string =>
filters != null && filters.length > 0
? Array.isArray(filters)
- ? filters
+ ? // Be aware of the surrounding parenthesis (as string inside literal) around filters.
+ `(${filters
.map(filter => `${CASE_SAVED_OBJECT}.attributes.${field}: ${filter}`)
- ?.join(` ${operator} `)
+ ?.join(` ${operator} `)})`
: `${CASE_SAVED_OBJECT}.attributes.${field}: ${filters}`
: '';
From cb914d408ebc20a3af267a4d4e52939cb40b4983 Mon Sep 17 00:00:00 2001
From: "Devin W. Hurley"
Date: Wed, 1 Apr 2020 16:45:16 -0400
Subject: [PATCH 02/99] [SIEM] [Detection Engine] Fixes all rules sorting
(#62039)
* fixes sorting to what it was in 7.6.1
* removes sortable=true from non-sortable columns, fixes naming of sortable column field from activate to enabled to match the field eui expects to sort on, fixes react render warning due to resetting tableRef's current field during a render
---
.../public/pages/detection_engine/rules/all/columns.tsx | 4 +---
.../public/pages/detection_engine/rules/all/index.tsx | 9 ++++-----
.../public/pages/detection_engine/rules/all/reducer.ts | 5 ++++-
.../rules/components/all_rules_tables/index.tsx | 4 ++--
4 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx
index a155f3eb2803c..5157bd81403e2 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/columns.tsx
@@ -144,7 +144,6 @@ export const getColumns = ({
);
},
- sortable: true,
truncateText: true,
width: '20%',
},
@@ -180,7 +179,7 @@ export const getColumns = ({
},
{
align: 'center',
- field: 'activate',
+ field: 'enabled',
name: i18n.COLUMN_ACTIVATE,
render: (value: Rule['enabled'], item: Rule) => (
{
);
},
- sortable: true,
truncateText: true,
width: '20%',
},
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx
index 4003b71b95d77..1a98272546440 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx
@@ -41,11 +41,12 @@ import { showRulesTable } from './helpers';
import { allRulesReducer, State } from './reducer';
import { RulesTableFilters } from './rules_table_filters/rules_table_filters';
+const SORT_FIELD = 'enabled';
const initialState: State = {
exportRuleIds: [],
filterOptions: {
filter: '',
- sortField: 'enabled',
+ sortField: SORT_FIELD,
sortOrder: 'desc',
},
loadingRuleIds: [],
@@ -127,9 +128,7 @@ export const AllRules = React.memo(
});
const sorting = useMemo(
- () => ({
- sort: { field: 'enabled', direction: filterOptions.sortOrder },
- }),
+ () => ({ sort: { field: 'enabled', direction: filterOptions.sortOrder } }),
[filterOptions.sortOrder]
);
@@ -171,7 +170,7 @@ export const AllRules = React.memo(
dispatch({
type: 'updateFilterOptions',
filterOptions: {
- sortField: 'enabled', // Only enabled is supported for sorting currently
+ sortField: SORT_FIELD, // Only enabled is supported for sorting currently
sortOrder: sort?.direction ?? 'desc',
},
pagination: { page: page.index + 1, perPage: page.size },
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/reducer.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/reducer.ts
index 0a4d169d13154..bc5297e7628b7 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/reducer.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/reducer.ts
@@ -66,7 +66,10 @@ export const allRulesReducer = (
tableRef.current != null &&
tableRef.current.changeSelection != null
) {
- tableRef.current.changeSelection([]);
+ // for future devs: eui basic table is not giving us a prop to set the value, so
+ // we are using the ref in setTimeout to reset on the next loop so that we
+ // do not get a warning telling us we are trying to update during a render
+ window.setTimeout(() => tableRef?.current?.changeSelection([]), 0);
}
return {
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/all_rules_tables/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/all_rules_tables/index.tsx
index 92ccbc864ab5a..0fd07f30a00b6 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/all_rules_tables/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/all_rules_tables/index.tsx
@@ -97,7 +97,7 @@ const AllRulesTablesComponent: React.FC = ({
onChange={tableOnChangeCallback}
pagination={paginationMemo}
ref={tableRef}
- {...sorting}
+ sorting={sorting}
selection={hasNoPermissions ? undefined : euiBasicTableSelectionProps}
/>
)}
@@ -111,7 +111,7 @@ const AllRulesTablesComponent: React.FC = ({
noItemsMessage={emptyPrompt}
onChange={tableOnChangeCallback}
pagination={paginationMemo}
- {...sorting}
+ sorting={sorting}
/>
)}
>
From a6906690aa23ac4cd63bd3163f06bd368b44ed8c Mon Sep 17 00:00:00 2001
From: spalger
Date: Wed, 1 Apr 2020 15:03:43 -0700
Subject: [PATCH 03/99] rename README.md to readme, avoiding issues with case
change
---
packages/elastic-datemath/{README.md => readme} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename packages/elastic-datemath/{README.md => readme} (100%)
diff --git a/packages/elastic-datemath/README.md b/packages/elastic-datemath/readme
similarity index 100%
rename from packages/elastic-datemath/README.md
rename to packages/elastic-datemath/readme
From 07be0660409f66b63e47507d9a273e48f51314f8 Mon Sep 17 00:00:00 2001
From: Rashmi Kulkarni
Date: Wed, 1 Apr 2020 15:20:47 -0700
Subject: [PATCH 04/99] accessibility tests for dashboard panel ( OSS)
(#62055)
* accessibility tests for dashboard panel
* added back the skipped test as it is still required to pass through the a11ySnapshot
Co-authored-by: Elastic Machine
---
test/accessibility/apps/dashboard_panel.ts | 79 ++++++++++++++++++++++
test/accessibility/config.ts | 1 +
2 files changed, 80 insertions(+)
create mode 100644 test/accessibility/apps/dashboard_panel.ts
diff --git a/test/accessibility/apps/dashboard_panel.ts b/test/accessibility/apps/dashboard_panel.ts
new file mode 100644
index 0000000000000..04821a50df618
--- /dev/null
+++ b/test/accessibility/apps/dashboard_panel.ts
@@ -0,0 +1,79 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { FtrProviderContext } from '../ftr_provider_context';
+
+export default function({ getService, getPageObjects }: FtrProviderContext) {
+ const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'home', 'settings']);
+ const a11y = getService('a11y');
+ const dashboardPanelActions = getService('dashboardPanelActions');
+ const testSubjects = getService('testSubjects');
+ const inspector = getService('inspector');
+
+ describe('Dashboard Panel', () => {
+ before(async () => {
+ await PageObjects.common.navigateToUrl('home', 'tutorial_directory/sampleData');
+ await PageObjects.home.addSampleDataSet('flights');
+ await PageObjects.common.navigateToApp('dashboard');
+ await testSubjects.click('dashboardListingTitleLink-[Flights]-Global-Flight-Dashboard');
+ });
+
+ it('dashboard panel open ', async () => {
+ const header = await dashboardPanelActions.getPanelHeading('[Flights] Airline Carrier');
+ await dashboardPanelActions.toggleContextMenu(header);
+ await a11y.testAppSnapshot();
+ // doing this again will close the Context Menu, so that next snapshot can start clean.
+ await dashboardPanelActions.toggleContextMenu(header);
+ });
+
+ it('dashboard panel inspect', async () => {
+ await dashboardPanelActions.openInspectorByTitle('[Flights] Airline Carrier');
+ await a11y.testAppSnapshot();
+ });
+
+ it('dashboard panel inspector view chooser ', async () => {
+ await testSubjects.click('inspectorViewChooser');
+ await a11y.testAppSnapshot();
+ await testSubjects.click('inspectorViewChooser');
+ });
+
+ it('dashboard panel inspector request statistics ', async () => {
+ await inspector.openInspectorRequestsView();
+ await a11y.testAppSnapshot();
+ });
+
+ it('dashboard panel inspector request', async () => {
+ await testSubjects.click('inspectorRequestDetailRequest');
+ await a11y.testAppSnapshot();
+ });
+
+ it('dashboard panel inspector response', async () => {
+ await testSubjects.click('inspectorRequestDetailResponse');
+ await a11y.testAppSnapshot();
+ await inspector.close();
+ });
+
+ it('dashboard panel full screen', async () => {
+ const header = await dashboardPanelActions.getPanelHeading('[Flights] Airline Carrier');
+ await dashboardPanelActions.toggleContextMenu(header);
+ await testSubjects.click('embeddablePanelAction-togglePanel');
+ await a11y.testAppSnapshot();
+ });
+ });
+}
diff --git a/test/accessibility/config.ts b/test/accessibility/config.ts
index dd8c59c1be835..bf71fd81aa199 100644
--- a/test/accessibility/config.ts
+++ b/test/accessibility/config.ts
@@ -30,6 +30,7 @@ export default async function({ readConfigFile }: FtrConfigProviderContext) {
testFiles: [
require.resolve('./apps/discover'),
require.resolve('./apps/dashboard'),
+ require.resolve('./apps/dashboard_panel'),
require.resolve('./apps/visualize'),
require.resolve('./apps/management'),
require.resolve('./apps/console'),
From 325f8e0ad55ef006d1ca1b0b393d0b35947a697a Mon Sep 17 00:00:00 2001
From: Lukas Olson
Date: Wed, 1 Apr 2020 15:45:42 -0700
Subject: [PATCH 05/99] Remove polling delay (#62099)
---
.../plugins/data_enhanced/public/search/es_search_strategy.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts
index 70bdcdfd3cf1f..c493e8ce86781 100644
--- a/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts
+++ b/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts
@@ -33,7 +33,7 @@ export const enhancedEsSearchStrategyProvider: TSearchStrategyProvider
Date: Wed, 1 Apr 2020 20:21:18 -0600
Subject: [PATCH 06/99] [Maps] Separate layer wizards for Clusters and heatmap
(#60870)
* [Maps] source registry and register seperate clusters and heat map sources
* split into to registries
* add EMS file source
* add geojson upload layer
* register rest of sources
* i18n changes
* ts lint errors
* fix jest test
* fix pew-pew source
* review feedback
* import registires in plugin so they exist in embeddable
* remove order parameter and move all layer registies into single file
* fix functionalt est
* pass constructor to sourceREgistry instead of factory
* review feedback
Co-authored-by: Elastic Machine
---
.../layer_addpanel/import_editor/view.js | 7 +-
.../layer_addpanel/source_editor/view.js | 20 +-
.../source_select/source_select.js | 25 +--
.../layer_addpanel/view.js | 20 +-
.../public/layers/layer_wizard_registry.ts | 30 +++
.../maps/public/layers/load_layer_wizards.js | 30 +++
.../maps/public/layers/sources/all_sources.js | 29 ---
.../client_file_source/geojson_file_source.js | 177 +++++++++---------
.../sources/client_file_source/index.js | 2 +-
.../ems_file_source/ems_file_source.js | 44 +++--
.../layers/sources/ems_file_source/index.js | 2 +-
.../sources/ems_tms_source/ems_tms_source.js | 46 +++--
.../layers/sources/ems_tms_source/index.js | 2 +-
.../create_source_editor.js | 57 +-----
.../es_geo_grid_source/es_geo_grid_source.js | 97 +++++++---
.../sources/es_geo_grid_source/index.js | 6 +-
.../es_geo_grid_source/render_as_select.tsx | 59 ++++++
.../es_pew_pew_source/es_pew_pew_source.js | 55 +++---
.../es_search_source/es_search_source.js | 63 ++++---
.../layers/sources/es_search_source/index.js | 2 +-
.../maps/public/layers/sources/es_source.js | 2 -
.../sources/kibana_regionmap_source/index.js | 2 +-
.../kibana_regionmap_source.js | 50 +++--
.../sources/kibana_tilemap_source/index.js | 2 +-
.../kibana_tilemap_source.js | 48 +++--
.../public/layers/sources/source_registry.ts | 35 ++++
.../public/layers/sources/wms_source/index.js | 2 +-
.../layers/sources/wms_source/wms_source.js | 57 +++---
.../public/layers/sources/xyz_tms_source.js | 44 +++--
x-pack/legacy/plugins/maps/public/plugin.ts | 4 +
.../maps/public/selectors/map_selectors.js | 10 +-
.../public/selectors/map_selectors.test.js | 1 -
x-pack/plugins/maps/common/constants.ts | 3 +
.../translations/translations/ja-JP.json | 5 -
.../translations/translations/zh-CN.json | 5 -
.../test/functional/page_objects/gis_page.js | 2 +-
36 files changed, 629 insertions(+), 416 deletions(-)
create mode 100644 x-pack/legacy/plugins/maps/public/layers/layer_wizard_registry.ts
create mode 100644 x-pack/legacy/plugins/maps/public/layers/load_layer_wizards.js
delete mode 100644 x-pack/legacy/plugins/maps/public/layers/sources/all_sources.js
create mode 100644 x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/render_as_select.tsx
create mode 100644 x-pack/legacy/plugins/maps/public/layers/sources/source_registry.ts
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/import_editor/view.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/import_editor/view.js
index e9ef38e17b188..762409b256286 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/import_editor/view.js
+++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/import_editor/view.js
@@ -5,13 +5,12 @@
*/
import React, { Fragment } from 'react';
-import { GeojsonFileSource } from '../../../layers/sources/client_file_source';
import { EuiSpacer, EuiPanel, EuiButtonEmpty } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
+import { uploadLayerWizardConfig } from '../../../layers/sources/client_file_source';
export const ImportEditor = ({ clearSource, isIndexingTriggered, ...props }) => {
const editorProperties = getEditorProperties({ isIndexingTriggered, ...props });
- const editor = GeojsonFileSource.renderEditor(editorProperties);
return (
{isIndexingTriggered ? null : (
@@ -25,7 +24,9 @@ export const ImportEditor = ({ clearSource, isIndexingTriggered, ...props }) =>
)}
- {editor}
+
+ {uploadLayerWizardConfig.renderWizard(editorProperties)}
+
);
};
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/source_editor/view.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/source_editor/view.js
index 45c508e0d5889..50312b68277fa 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/source_editor/view.js
+++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/source_editor/view.js
@@ -5,28 +5,20 @@
*/
import React, { Fragment } from 'react';
-import { ALL_SOURCES } from '../../../layers/sources/all_sources';
import { EuiSpacer, EuiPanel, EuiButtonEmpty } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
export const SourceEditor = ({
clearSource,
- sourceType,
+ layerWizard,
isIndexingTriggered,
inspectorAdapters,
previewLayer,
}) => {
- const editorProperties = {
- onPreviewSource: previewLayer,
- inspectorAdapters,
- };
- const Source = ALL_SOURCES.find(Source => {
- return Source.type === sourceType;
- });
- if (!Source) {
- throw new Error(`Unexpected source type: ${sourceType}`);
+ if (!layerWizard) {
+ return null;
}
- const editor = Source.renderEditor(editorProperties);
+
return (
{isIndexingTriggered ? null : (
@@ -40,7 +32,9 @@ export const SourceEditor = ({
)}
- {editor}
+
+ {layerWizard.renderWizard({ onPreviewSource: previewLayer, inspectorAdapters })}
+
);
};
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/source_select/source_select.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/source_select/source_select.js
index 574a57b1041a0..b34a432bec88c 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/source_select/source_select.js
+++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/source_select/source_select.js
@@ -5,30 +5,33 @@
*/
import React, { Fragment } from 'react';
-import { ALL_SOURCES } from '../../../layers/sources/all_sources';
+import { getLayerWizards } from '../../../layers/layer_wizard_registry';
import { EuiTitle, EuiSpacer, EuiCard, EuiIcon } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import _ from 'lodash';
export function SourceSelect({ updateSourceSelection }) {
- const sourceCards = ALL_SOURCES.map(Source => {
- const icon = Source.icon ? : null;
+ const sourceCards = getLayerWizards().map(layerWizard => {
+ const icon = layerWizard.icon ? : null;
- const sourceTitle = Source.title;
+ const onClick = () => {
+ updateSourceSelection({
+ layerWizard: layerWizard,
+ isIndexingSource: !!layerWizard.isIndexingSource,
+ });
+ };
return (
-
+
- updateSourceSelection({ type: Source.type, isIndexingSource: Source.isIndexingSource })
- }
- description={Source.description}
+ onClick={onClick}
+ description={layerWizard.description}
layout="horizontal"
- data-test-subj={_.camelCase(Source.title)}
+ data-test-subj={_.camelCase(layerWizard.title)}
/>
);
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/view.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/view.js
index 425cc1cae3649..a54df69471aa0 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/view.js
+++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/view.js
@@ -14,7 +14,7 @@ import { i18n } from '@kbn/i18n';
export class AddLayerPanel extends Component {
state = {
- sourceType: null,
+ layerWizard: null,
layer: null,
importView: false,
layerImportAddReady: false,
@@ -35,9 +35,9 @@ export class AddLayerPanel extends Component {
}
_getPanelDescription() {
- const { sourceType, importView, layerImportAddReady } = this.state;
+ const { layerWizard, importView, layerImportAddReady } = this.state;
let panelDescription;
- if (!sourceType) {
+ if (!layerWizard) {
panelDescription = i18n.translate('xpack.maps.addLayerPanel.selectSource', {
defaultMessage: 'Select source',
});
@@ -85,13 +85,13 @@ export class AddLayerPanel extends Component {
this.setState({
layer: null,
- ...(!keepSourceType ? { sourceType: null, importView: false } : {}),
+ ...(!keepSourceType ? { layerWizard: null, importView: false } : {}),
});
this.props.removeTransientLayer();
};
- _onSourceSelectionChange = ({ type, isIndexingSource }) => {
- this.setState({ sourceType: type, importView: isIndexingSource });
+ _onSourceSelectionChange = ({ layerWizard, isIndexingSource }) => {
+ this.setState({ layerWizard, importView: isIndexingSource });
};
_layerAddHandler = () => {
@@ -118,8 +118,8 @@ export class AddLayerPanel extends Component {
};
_renderAddLayerPanel() {
- const { sourceType, importView } = this.state;
- if (!sourceType) {
+ const { layerWizard, importView } = this.state;
+ if (!layerWizard) {
return ;
}
if (importView) {
@@ -134,7 +134,7 @@ export class AddLayerPanel extends Component {
return (
);
@@ -148,7 +148,7 @@ export class AddLayerPanel extends Component {
return (
void;
+ inspectorAdapters: unknown;
+ }): unknown;
+ title: string;
+};
+
+const registry: LayerWizard[] = [];
+
+export function registerLayerWizard(layerWizard: LayerWizard) {
+ registry.push(layerWizard);
+}
+
+export function getLayerWizards(): LayerWizard[] {
+ return [...registry];
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/load_layer_wizards.js b/x-pack/legacy/plugins/maps/public/layers/load_layer_wizards.js
new file mode 100644
index 0000000000000..d0169165eaa35
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/load_layer_wizards.js
@@ -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 { registerLayerWizard } from './layer_wizard_registry';
+import { uploadLayerWizardConfig } from './sources/client_file_source';
+import { esDocumentsLayerWizardConfig } from './sources/es_search_source';
+import { clustersLayerWizardConfig, heatmapLayerWizardConfig } from './sources/es_geo_grid_source';
+import { point2PointLayerWizardConfig } from './sources/es_pew_pew_source/es_pew_pew_source';
+import { emsBoundariesLayerWizardConfig } from './sources/ems_file_source';
+import { emsBaseMapLayerWizardConfig } from './sources/ems_tms_source';
+import { kibanaRegionMapLayerWizardConfig } from './sources/kibana_regionmap_source';
+import { kibanaBasemapLayerWizardConfig } from './sources/kibana_tilemap_source';
+import { tmsLayerWizardConfig } from './sources/xyz_tms_source';
+import { wmsLayerWizardConfig } from './sources/wms_source';
+
+// Registration order determines display order
+registerLayerWizard(uploadLayerWizardConfig);
+registerLayerWizard(esDocumentsLayerWizardConfig);
+registerLayerWizard(clustersLayerWizardConfig);
+registerLayerWizard(heatmapLayerWizardConfig);
+registerLayerWizard(point2PointLayerWizardConfig);
+registerLayerWizard(emsBoundariesLayerWizardConfig);
+registerLayerWizard(emsBaseMapLayerWizardConfig);
+registerLayerWizard(kibanaRegionMapLayerWizardConfig);
+registerLayerWizard(kibanaBasemapLayerWizardConfig);
+registerLayerWizard(tmsLayerWizardConfig);
+registerLayerWizard(wmsLayerWizardConfig);
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/all_sources.js b/x-pack/legacy/plugins/maps/public/layers/sources/all_sources.js
deleted file mode 100644
index 6a518609dd77f..0000000000000
--- a/x-pack/legacy/plugins/maps/public/layers/sources/all_sources.js
+++ /dev/null
@@ -1,29 +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 { EMSFileSource } from './ems_file_source';
-import { GeojsonFileSource } from './client_file_source';
-import { KibanaRegionmapSource } from './kibana_regionmap_source';
-import { XYZTMSSource } from './xyz_tms_source';
-import { EMSTMSSource } from './ems_tms_source';
-import { WMSSource } from './wms_source';
-import { KibanaTilemapSource } from './kibana_tilemap_source';
-import { ESGeoGridSource } from './es_geo_grid_source';
-import { ESSearchSource } from './es_search_source';
-import { ESPewPewSource } from './es_pew_pew_source/es_pew_pew_source';
-
-export const ALL_SOURCES = [
- GeojsonFileSource,
- ESSearchSource,
- ESGeoGridSource,
- ESPewPewSource,
- EMSFileSource,
- EMSTMSSource,
- KibanaRegionmapSource,
- KibanaTilemapSource,
- XYZTMSSource,
- WMSSource,
-];
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js
index a38669fcd1d1a..1003f8329da22 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js
@@ -16,16 +16,11 @@ import { ESSearchSource } from '../es_search_source';
import uuid from 'uuid/v4';
import _ from 'lodash';
import { i18n } from '@kbn/i18n';
+import { registerSource } from '../source_registry';
export class GeojsonFileSource extends AbstractVectorSource {
static type = GEOJSON_FILE;
- static title = i18n.translate('xpack.maps.source.geojsonFileTitle', {
- defaultMessage: 'Uploaded GeoJSON',
- });
- static description = i18n.translate('xpack.maps.source.geojsonFileDescription', {
- defaultMessage: 'Upload and index GeoJSON data in Elasticsearch',
- });
- static icon = 'importAction';
+
static isIndexingSource = true;
static createDescriptor(geoJson, name) {
@@ -59,62 +54,93 @@ export class GeojsonFileSource extends AbstractVectorSource {
};
}
- static viewIndexedData = (
- addAndViewSource,
- inspectorAdapters,
- importSuccessHandler,
- importErrorHandler
- ) => {
- return (indexResponses = {}) => {
- const { indexDataResp, indexPatternResp } = indexResponses;
-
- const indexCreationFailed = !(indexDataResp && indexDataResp.success);
- const allDocsFailed = indexDataResp.failures.length === indexDataResp.docCount;
- const indexPatternCreationFailed = !(indexPatternResp && indexPatternResp.success);
-
- if (indexCreationFailed || allDocsFailed || indexPatternCreationFailed) {
- importErrorHandler(indexResponses);
- return;
- }
- const { fields, id } = indexPatternResp;
- const geoFieldArr = fields.filter(field =>
- Object.values(ES_GEO_FIELD_TYPE).includes(field.type)
- );
- const geoField = _.get(geoFieldArr, '[0].name');
- const indexPatternId = id;
- if (!indexPatternId || !geoField) {
- addAndViewSource(null);
- } else {
- // Only turn on bounds filter for large doc counts
- const filterByMapBounds = indexDataResp.docCount > DEFAULT_MAX_RESULT_WINDOW;
- const source = new ESSearchSource(
- {
- id: uuid(),
- indexPatternId,
- geoField,
- filterByMapBounds,
- },
- inspectorAdapters
- );
- addAndViewSource(source);
- importSuccessHandler(indexResponses);
- }
+ async getGeoJsonWithMeta() {
+ return {
+ data: this._descriptor.__featureCollection,
+ meta: {},
};
+ }
+
+ async getDisplayName() {
+ return this._descriptor.name;
+ }
+
+ canFormatFeatureProperties() {
+ return true;
+ }
+
+ shouldBeIndexed() {
+ return GeojsonFileSource.isIndexingSource;
+ }
+}
+
+const viewIndexedData = (
+ addAndViewSource,
+ inspectorAdapters,
+ importSuccessHandler,
+ importErrorHandler
+) => {
+ return (indexResponses = {}) => {
+ const { indexDataResp, indexPatternResp } = indexResponses;
+
+ const indexCreationFailed = !(indexDataResp && indexDataResp.success);
+ const allDocsFailed = indexDataResp.failures.length === indexDataResp.docCount;
+ const indexPatternCreationFailed = !(indexPatternResp && indexPatternResp.success);
+
+ if (indexCreationFailed || allDocsFailed || indexPatternCreationFailed) {
+ importErrorHandler(indexResponses);
+ return;
+ }
+ const { fields, id } = indexPatternResp;
+ const geoFieldArr = fields.filter(field =>
+ Object.values(ES_GEO_FIELD_TYPE).includes(field.type)
+ );
+ const geoField = _.get(geoFieldArr, '[0].name');
+ const indexPatternId = id;
+ if (!indexPatternId || !geoField) {
+ addAndViewSource(null);
+ } else {
+ // Only turn on bounds filter for large doc counts
+ const filterByMapBounds = indexDataResp.docCount > DEFAULT_MAX_RESULT_WINDOW;
+ const source = new ESSearchSource(
+ {
+ id: uuid(),
+ indexPatternId,
+ geoField,
+ filterByMapBounds,
+ },
+ inspectorAdapters
+ );
+ addAndViewSource(source);
+ importSuccessHandler(indexResponses);
+ }
};
+};
- static previewGeojsonFile = (onPreviewSource, inspectorAdapters) => {
- return (geojsonFile, name) => {
- if (!geojsonFile) {
- onPreviewSource(null);
- return;
- }
- const sourceDescriptor = GeojsonFileSource.createDescriptor(geojsonFile, name);
- const source = new GeojsonFileSource(sourceDescriptor, inspectorAdapters);
- onPreviewSource(source);
- };
+const previewGeojsonFile = (onPreviewSource, inspectorAdapters) => {
+ return (geojsonFile, name) => {
+ if (!geojsonFile) {
+ onPreviewSource(null);
+ return;
+ }
+ const sourceDescriptor = GeojsonFileSource.createDescriptor(geojsonFile, name);
+ const source = new GeojsonFileSource(sourceDescriptor, inspectorAdapters);
+ onPreviewSource(source);
};
+};
+
+registerSource({
+ ConstructorFunction: GeojsonFileSource,
+ type: GEOJSON_FILE,
+});
- static renderEditor({
+export const uploadLayerWizardConfig = {
+ description: i18n.translate('xpack.maps.source.geojsonFileDescription', {
+ defaultMessage: 'Index GeoJSON data in Elasticsearch',
+ }),
+ icon: 'importAction',
+ isIndexingSource: true,
+ renderWizard: ({
onPreviewSource,
inspectorAdapters,
addAndViewSource,
@@ -123,15 +149,12 @@ export class GeojsonFileSource extends AbstractVectorSource {
onIndexReady,
importSuccessHandler,
importErrorHandler,
- }) {
+ }) => {
return (
);
- }
-
- async getGeoJsonWithMeta() {
- return {
- data: this._descriptor.__featureCollection,
- meta: {},
- };
- }
-
- async getDisplayName() {
- return this._descriptor.name;
- }
-
- canFormatFeatureProperties() {
- return true;
- }
-
- shouldBeIndexed() {
- return GeojsonFileSource.isIndexingSource;
- }
-}
+ },
+ title: i18n.translate('xpack.maps.source.geojsonFileTitle', {
+ defaultMessage: 'Upload GeoJSON',
+ }),
+};
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/index.js b/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/index.js
index cf0d15dcb747a..a6a31def4b231 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/index.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/client_file_source/index.js
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { GeojsonFileSource } from './geojson_file_source';
+export { GeojsonFileSource, uploadLayerWizardConfig } from './geojson_file_source';
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js
index 524f030862768..d3ccc0cb55821 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js
@@ -14,16 +14,14 @@ import { i18n } from '@kbn/i18n';
import { getDataSourceLabel } from '../../../../common/i18n_getters';
import { UpdateSourceEditor } from './update_source_editor';
import { EMSFileField } from '../../fields/ems_file_field';
+import { registerSource } from '../source_registry';
+
+const sourceTitle = i18n.translate('xpack.maps.source.emsFileTitle', {
+ defaultMessage: 'EMS Boundaries',
+});
export class EMSFileSource extends AbstractVectorSource {
static type = EMS_FILE;
- static title = i18n.translate('xpack.maps.source.emsFileTitle', {
- defaultMessage: 'EMS Boundaries',
- });
- static description = i18n.translate('xpack.maps.source.emsFileDescription', {
- defaultMessage: 'Administrative boundaries from Elastic Maps Service',
- });
- static icon = 'emsApp';
static createDescriptor({ id, tooltipProperties = [] }) {
return {
@@ -33,15 +31,6 @@ export class EMSFileSource extends AbstractVectorSource {
};
}
- static renderEditor({ onPreviewSource, inspectorAdapters }) {
- const onSourceConfigChange = sourceConfig => {
- const sourceDescriptor = EMSFileSource.createDescriptor(sourceConfig);
- const source = new EMSFileSource(sourceDescriptor, inspectorAdapters);
- onPreviewSource(source);
- };
- return ;
- }
-
constructor(descriptor, inspectorAdapters) {
super(EMSFileSource.createDescriptor(descriptor), inspectorAdapters);
this._tooltipFields = this._descriptor.tooltipProperties.map(propertyKey =>
@@ -118,7 +107,7 @@ export class EMSFileSource extends AbstractVectorSource {
return [
{
label: getDataSourceLabel(),
- value: EMSFileSource.title,
+ value: sourceTitle,
},
{
label: i18n.translate('xpack.maps.source.emsFile.layerLabel', {
@@ -167,3 +156,24 @@ export class EMSFileSource extends AbstractVectorSource {
return [VECTOR_SHAPE_TYPES.POLYGON];
}
}
+
+registerSource({
+ ConstructorFunction: EMSFileSource,
+ type: EMS_FILE,
+});
+
+export const emsBoundariesLayerWizardConfig = {
+ description: i18n.translate('xpack.maps.source.emsFileDescription', {
+ defaultMessage: 'Administrative boundaries from Elastic Maps Service',
+ }),
+ icon: 'emsApp',
+ renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
+ const onSourceConfigChange = sourceConfig => {
+ const sourceDescriptor = EMSFileSource.createDescriptor(sourceConfig);
+ const source = new EMSFileSource(sourceDescriptor, inspectorAdapters);
+ onPreviewSource(source);
+ };
+ return ;
+ },
+ title: sourceTitle,
+};
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/index.js b/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/index.js
index 9d0e503eb08ba..28fbc04a1a032 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/index.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/index.js
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { EMSFileSource } from './ems_file_source';
+export { EMSFileSource, emsBoundariesLayerWizardConfig } from './ems_file_source';
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/ems_tms_source/ems_tms_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/ems_tms_source/ems_tms_source.js
index 5a2124622694c..1da3680dfdc86 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/ems_tms_source/ems_tms_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/ems_tms_source/ems_tms_source.js
@@ -16,16 +16,14 @@ import { i18n } from '@kbn/i18n';
import { getDataSourceLabel } from '../../../../common/i18n_getters';
import { EMS_TMS } from '../../../../common/constants';
import { getInjectedVarFunc, getUiSettings } from '../../../kibana_services';
+import { registerSource } from '../source_registry';
+
+const sourceTitle = i18n.translate('xpack.maps.source.emsTileTitle', {
+ defaultMessage: 'EMS Basemaps',
+});
export class EMSTMSSource extends AbstractTMSSource {
static type = EMS_TMS;
- static title = i18n.translate('xpack.maps.source.emsTileTitle', {
- defaultMessage: 'EMS Basemaps',
- });
- static description = i18n.translate('xpack.maps.source.emsTileDescription', {
- defaultMessage: 'Tile map service from Elastic Maps Service',
- });
- static icon = 'emsApp';
static createDescriptor(sourceConfig) {
return {
@@ -35,16 +33,6 @@ export class EMSTMSSource extends AbstractTMSSource {
};
}
- static renderEditor({ onPreviewSource, inspectorAdapters }) {
- const onSourceConfigChange = sourceConfig => {
- const descriptor = EMSTMSSource.createDescriptor(sourceConfig);
- const source = new EMSTMSSource(descriptor, inspectorAdapters);
- onPreviewSource(source);
- };
-
- return ;
- }
-
constructor(descriptor, inspectorAdapters) {
super(
{
@@ -69,7 +57,7 @@ export class EMSTMSSource extends AbstractTMSSource {
return [
{
label: getDataSourceLabel(),
- value: EMSTMSSource.title,
+ value: sourceTitle,
},
{
label: i18n.translate('xpack.maps.source.emsTile.serviceId', {
@@ -157,3 +145,25 @@ export class EMSTMSSource extends AbstractTMSSource {
return isDarkMode ? emsTileLayerId.dark : emsTileLayerId.bright;
}
}
+
+registerSource({
+ ConstructorFunction: EMSTMSSource,
+ type: EMS_TMS,
+});
+
+export const emsBaseMapLayerWizardConfig = {
+ description: i18n.translate('xpack.maps.source.emsTileDescription', {
+ defaultMessage: 'Tile map service from Elastic Maps Service',
+ }),
+ icon: 'emsApp',
+ renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
+ const onSourceConfigChange = sourceConfig => {
+ const descriptor = EMSTMSSource.createDescriptor(sourceConfig);
+ const source = new EMSTMSSource(descriptor, inspectorAdapters);
+ onPreviewSource(source);
+ };
+
+ return ;
+ },
+ title: sourceTitle,
+};
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/ems_tms_source/index.js b/x-pack/legacy/plugins/maps/public/layers/sources/ems_tms_source/index.js
index 81306578db4ae..60a4c9b1de891 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/ems_tms_source/index.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/ems_tms_source/index.js
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { EMSTMSSource } from './ems_tms_source';
+export { EMSTMSSource, emsBaseMapLayerWizardConfig } from './ems_tms_source';
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js
index 148683269ef78..4aec390bec745 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js
@@ -14,32 +14,12 @@ import { getIndexPatternService, getIndexPatternSelectComponent } from '../../..
import { NoIndexPatternCallout } from '../../../components/no_index_pattern_callout';
import { i18n } from '@kbn/i18n';
-import { EuiFormRow, EuiComboBox, EuiSpacer } from '@elastic/eui';
+import { EuiFormRow, EuiSpacer } from '@elastic/eui';
import {
AGGREGATABLE_GEO_FIELD_TYPES,
getAggregatableGeoFields,
} from '../../../index_pattern_util';
-
-const requestTypeOptions = [
- {
- label: i18n.translate('xpack.maps.source.esGeoGrid.gridRectangleDropdownOption', {
- defaultMessage: 'grid rectangles',
- }),
- value: RENDER_AS.GRID,
- },
- {
- label: i18n.translate('xpack.maps.source.esGeoGrid.heatmapDropdownOption', {
- defaultMessage: 'heat map',
- }),
- value: RENDER_AS.HEATMAP,
- },
- {
- label: i18n.translate('xpack.maps.source.esGeoGrid.pointsDropdownOption', {
- defaultMessage: 'clusters',
- }),
- value: RENDER_AS.POINT,
- },
-];
+import { RenderAsSelect } from './render_as_select';
export class CreateSourceEditor extends Component {
static propTypes = {
@@ -50,7 +30,7 @@ export class CreateSourceEditor extends Component {
isLoadingIndexPattern: false,
indexPatternId: '',
geoField: '',
- requestType: requestTypeOptions[0],
+ requestType: this.props.requestType,
noGeoIndexPatternsExist: false,
};
@@ -126,10 +106,10 @@ export class CreateSourceEditor extends Component {
);
};
- _onRequestTypeSelect = selectedOptions => {
+ _onRequestTypeSelect = newValue => {
this.setState(
{
- requestType: selectedOptions[0],
+ requestType: newValue,
},
this.previewLayer
);
@@ -139,9 +119,7 @@ export class CreateSourceEditor extends Component {
const { indexPatternId, geoField, requestType } = this.state;
const sourceConfig =
- indexPatternId && geoField
- ? { indexPatternId, geoField, requestType: requestType.value }
- : null;
+ indexPatternId && geoField ? { indexPatternId, geoField, requestType } : null;
this.props.onSourceConfigChange(sourceConfig);
};
@@ -176,28 +154,13 @@ export class CreateSourceEditor extends Component {
);
}
- _renderLayerSelect() {
- if (!this.state.indexPattern) {
+ _renderRenderAsSelect() {
+ if (this.state.requestType === RENDER_AS.HEATMAP || !this.state.indexPattern) {
return null;
}
return (
-
-
-
+
);
}
@@ -243,7 +206,7 @@ export class CreateSourceEditor extends Component {
{this._renderNoIndexPatternWarning()}
{this._renderIndexPatternSelect()}
{this._renderGeoSelect()}
- {this._renderLayerSelect()}
+ {this._renderRenderAsSelect()}
);
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js
index 405c8a61bfca6..dec802ac3cf1a 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js
@@ -32,17 +32,20 @@ import { AbstractESAggSource } from '../es_agg_source';
import { DynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property';
import { StaticStyleProperty } from '../../styles/vector/properties/static_style_property';
import { DataRequestAbortError } from '../../util/data_request';
+import { registerSource } from '../source_registry';
export const MAX_GEOTILE_LEVEL = 29;
+const clustersTitle = i18n.translate('xpack.maps.source.esGridClustersTitle', {
+ defaultMessage: 'Clusters and grids',
+});
+
+const heatmapTitle = i18n.translate('xpack.maps.source.esGridHeatmapTitle', {
+ defaultMessage: 'Heat map',
+});
+
export class ESGeoGridSource extends AbstractESAggSource {
static type = ES_GEO_GRID;
- static title = i18n.translate('xpack.maps.source.esGridTitle', {
- defaultMessage: 'Grid aggregation',
- });
- static description = i18n.translate('xpack.maps.source.esGridDescription', {
- defaultMessage: 'Geospatial data grouped in grids with metrics for each gridded cell',
- });
static createDescriptor({ indexPatternId, geoField, requestType, resolution }) {
return {
@@ -55,21 +58,6 @@ export class ESGeoGridSource extends AbstractESAggSource {
};
}
- static renderEditor({ onPreviewSource, inspectorAdapters }) {
- const onSourceConfigChange = sourceConfig => {
- if (!sourceConfig) {
- onPreviewSource(null);
- return;
- }
-
- const sourceDescriptor = ESGeoGridSource.createDescriptor(sourceConfig);
- const source = new ESGeoGridSource(sourceDescriptor, inspectorAdapters);
- onPreviewSource(source);
- };
-
- return ;
- }
-
renderSourceSettingsEditor({ onChange }) {
return (
{
+ const onSourceConfigChange = sourceConfig => {
+ if (!sourceConfig) {
+ onPreviewSource(null);
+ return;
+ }
+
+ const sourceDescriptor = ESGeoGridSource.createDescriptor(sourceConfig);
+ const source = new ESGeoGridSource(sourceDescriptor, inspectorAdapters);
+ onPreviewSource(source);
+ };
+
+ return (
+
+ );
+ },
+ title: clustersTitle,
+};
+
+export const heatmapLayerWizardConfig = {
+ description: i18n.translate('xpack.maps.source.esGridHeatmapDescription', {
+ defaultMessage: 'Geospatial data grouped in grids to show density',
+ }),
+ icon: 'logoElasticsearch',
+ renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
+ const onSourceConfigChange = sourceConfig => {
+ if (!sourceConfig) {
+ onPreviewSource(null);
+ return;
+ }
+
+ const sourceDescriptor = ESGeoGridSource.createDescriptor(sourceConfig);
+ const source = new ESGeoGridSource(sourceDescriptor, inspectorAdapters);
+ onPreviewSource(source);
+ };
+
+ return (
+
+ );
+ },
+ title: heatmapTitle,
+};
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/index.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/index.js
index 58d74c04c5552..c2fa2356b1a3e 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/index.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/index.js
@@ -4,4 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { ESGeoGridSource } from './es_geo_grid_source';
+export {
+ ESGeoGridSource,
+ clustersLayerWizardConfig,
+ heatmapLayerWizardConfig,
+} from './es_geo_grid_source';
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/render_as_select.tsx b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/render_as_select.tsx
new file mode 100644
index 0000000000000..c82781ede186f
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/render_as_select.tsx
@@ -0,0 +1,59 @@
+/*
+ * 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 React from 'react';
+import { EuiFormRow, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { RENDER_AS } from '../../../../common/constants';
+
+const options = [
+ {
+ label: i18n.translate('xpack.maps.source.esGeoGrid.pointsDropdownOption', {
+ defaultMessage: 'clusters',
+ }),
+ value: RENDER_AS.POINT,
+ },
+ {
+ label: i18n.translate('xpack.maps.source.esGeoGrid.gridRectangleDropdownOption', {
+ defaultMessage: 'grids',
+ }),
+ value: RENDER_AS.GRID,
+ },
+];
+
+export function RenderAsSelect(props: {
+ renderAs: RENDER_AS;
+ onChange: (newValue: RENDER_AS) => void;
+}) {
+ function onChange(selectedOptions: Array>) {
+ if (!selectedOptions || !selectedOptions.length) {
+ return;
+ }
+ props.onChange(selectedOptions[0].value as RENDER_AS);
+ }
+
+ const selectedOptions = [];
+ const selectedOption = options.find(option => option.value === props.renderAs);
+ if (selectedOption) {
+ selectedOptions.push(selectedOption);
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js
index 5f6cc0a46dfb2..da2b663746b9d 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js
@@ -26,17 +26,16 @@ import { AbstractESAggSource } from '../es_agg_source';
import { DynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property';
import { COLOR_GRADIENTS } from '../../styles/color_utils';
import { indexPatterns } from '../../../../../../../../src/plugins/data/public';
+import { registerSource } from '../source_registry';
const MAX_GEOTILE_LEVEL = 29;
+const sourceTitle = i18n.translate('xpack.maps.source.pewPewTitle', {
+ defaultMessage: 'Point to point',
+});
+
export class ESPewPewSource extends AbstractESAggSource {
static type = ES_PEW_PEW;
- static title = i18n.translate('xpack.maps.source.pewPewTitle', {
- defaultMessage: 'Point to point',
- });
- static description = i18n.translate('xpack.maps.source.pewPewDescription', {
- defaultMessage: 'Aggregated data paths between the source and destination',
- });
static createDescriptor({ indexPatternId, sourceGeoField, destGeoField }) {
return {
@@ -48,21 +47,6 @@ export class ESPewPewSource extends AbstractESAggSource {
};
}
- static renderEditor({ onPreviewSource, inspectorAdapters }) {
- const onSourceConfigChange = sourceConfig => {
- if (!sourceConfig) {
- onPreviewSource(null);
- return;
- }
-
- const sourceDescriptor = ESPewPewSource.createDescriptor(sourceConfig);
- const source = new ESPewPewSource(sourceDescriptor, inspectorAdapters);
- onPreviewSource(source);
- };
-
- return ;
- }
-
renderSourceSettingsEditor({ onChange }) {
return (
{
+ const onSourceConfigChange = sourceConfig => {
+ if (!sourceConfig) {
+ onPreviewSource(null);
+ return;
+ }
+
+ const sourceDescriptor = ESPewPewSource.createDescriptor(sourceConfig);
+ const source = new ESPewPewSource(sourceDescriptor, inspectorAdapters);
+ onPreviewSource(source);
+ };
+
+ return ;
+ },
+ title: sourceTitle,
+};
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js
index cd44ef49623fa..ce9932bd15cea 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js
@@ -32,6 +32,11 @@ import { BlendedVectorLayer } from '../../blended_vector_layer';
import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants';
import { ESDocField } from '../../fields/es_doc_field';
import { getField, addFieldToDSL } from '../../util/es_agg_utils';
+import { registerSource } from '../source_registry';
+
+const sourceTitle = i18n.translate('xpack.maps.source.esSearchTitle', {
+ defaultMessage: 'Documents',
+});
function getDocValueAndSourceFields(indexPattern, fieldNames) {
const docValueFields = [];
@@ -65,31 +70,6 @@ function getDocValueAndSourceFields(indexPattern, fieldNames) {
export class ESSearchSource extends AbstractESSource {
static type = ES_SEARCH;
- static title = i18n.translate('xpack.maps.source.esSearchTitle', {
- defaultMessage: 'Documents',
- });
- static description = i18n.translate('xpack.maps.source.esSearchDescription', {
- defaultMessage: 'Vector data from a Kibana index pattern',
- });
-
- static renderEditor({ onPreviewSource, inspectorAdapters }) {
- const onSourceConfigChange = sourceConfig => {
- if (!sourceConfig) {
- onPreviewSource(null);
- return;
- }
-
- const source = new ESSearchSource(
- {
- id: uuid(),
- ...sourceConfig,
- },
- inspectorAdapters
- );
- onPreviewSource(source);
- };
- return ;
- }
constructor(descriptor, inspectorAdapters) {
super(
@@ -206,7 +186,7 @@ export class ESSearchSource extends AbstractESSource {
return [
{
label: getDataSourceLabel(),
- value: ESSearchSource.title,
+ value: sourceTitle,
},
{
label: i18n.translate('xpack.maps.source.esSearch.indexPatternLabel', {
@@ -587,3 +567,34 @@ export class ESSearchSource extends AbstractESSource {
};
}
}
+
+registerSource({
+ ConstructorFunction: ESSearchSource,
+ type: ES_SEARCH,
+});
+
+export const esDocumentsLayerWizardConfig = {
+ description: i18n.translate('xpack.maps.source.esSearchDescription', {
+ defaultMessage: 'Vector data from a Kibana index pattern',
+ }),
+ icon: 'logoElasticsearch',
+ renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
+ const onSourceConfigChange = sourceConfig => {
+ if (!sourceConfig) {
+ onPreviewSource(null);
+ return;
+ }
+
+ const source = new ESSearchSource(
+ {
+ id: uuid(),
+ ...sourceConfig,
+ },
+ inspectorAdapters
+ );
+ onPreviewSource(source);
+ };
+ return ;
+ },
+ title: sourceTitle,
+};
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/index.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/index.js
index 5fea38ee274d9..2c401ac92567e 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/index.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/index.js
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { ESSearchSource } from './es_search_source';
+export { ESSearchSource, esDocumentsLayerWizardConfig } from './es_search_source';
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
index 9dc3067a70436..bf04a73cfba77 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
@@ -23,8 +23,6 @@ import { DataRequestAbortError } from '../util/data_request';
import { expandToTileBoundaries } from './es_geo_grid_source/geo_tile_utils';
export class AbstractESSource extends AbstractVectorSource {
- static icon = 'logoElasticsearch';
-
constructor(descriptor, inspectorAdapters) {
super(
{
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/kibana_regionmap_source/index.js b/x-pack/legacy/plugins/maps/public/layers/sources/kibana_regionmap_source/index.js
index d54b135239a63..00c3bfc5f17c6 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/kibana_regionmap_source/index.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/kibana_regionmap_source/index.js
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { KibanaRegionmapSource } from './kibana_regionmap_source';
+export { KibanaRegionmapSource, kibanaRegionMapLayerWizardConfig } from './kibana_regionmap_source';
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/kibana_regionmap_source/kibana_regionmap_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/kibana_regionmap_source/kibana_regionmap_source.js
index 276a3377aaae2..7f4bcfa41f7c4 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/kibana_regionmap_source/kibana_regionmap_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/kibana_regionmap_source/kibana_regionmap_source.js
@@ -10,18 +10,16 @@ import { CreateSourceEditor } from './create_source_editor';
import { getKibanaRegionList } from '../../../meta';
import { i18n } from '@kbn/i18n';
import { getDataSourceLabel } from '../../../../common/i18n_getters';
-import { FIELD_ORIGIN } from '../../../../common/constants';
+import { FIELD_ORIGIN, REGIONMAP_FILE } from '../../../../common/constants';
import { KibanaRegionField } from '../../fields/kibana_region_field';
+import { registerSource } from '../source_registry';
+
+const sourceTitle = i18n.translate('xpack.maps.source.kbnRegionMapTitle', {
+ defaultMessage: 'Configured GeoJSON',
+});
export class KibanaRegionmapSource extends AbstractVectorSource {
- static type = 'REGIONMAP_FILE';
- static title = i18n.translate('xpack.maps.source.kbnRegionMapTitle', {
- defaultMessage: 'Configured GeoJSON',
- });
- static description = i18n.translate('xpack.maps.source.kbnRegionMapDescription', {
- defaultMessage: 'Vector data from hosted GeoJSON configured in kibana.yml',
- });
- static icon = 'logoKibana';
+ static type = REGIONMAP_FILE;
static createDescriptor({ name }) {
return {
@@ -30,16 +28,6 @@ export class KibanaRegionmapSource extends AbstractVectorSource {
};
}
- static renderEditor = ({ onPreviewSource, inspectorAdapters }) => {
- const onSourceConfigChange = sourceConfig => {
- const sourceDescriptor = KibanaRegionmapSource.createDescriptor(sourceConfig);
- const source = new KibanaRegionmapSource(sourceDescriptor, inspectorAdapters);
- onPreviewSource(source);
- };
-
- return ;
- };
-
createField({ fieldName }) {
return new KibanaRegionField({
fieldName,
@@ -52,7 +40,7 @@ export class KibanaRegionmapSource extends AbstractVectorSource {
return [
{
label: getDataSourceLabel(),
- value: KibanaRegionmapSource.title,
+ value: sourceTitle,
},
{
label: i18n.translate('xpack.maps.source.kbnRegionMap.vectorLayerLabel', {
@@ -108,3 +96,25 @@ export class KibanaRegionmapSource extends AbstractVectorSource {
return true;
}
}
+
+registerSource({
+ ConstructorFunction: KibanaRegionmapSource,
+ type: REGIONMAP_FILE,
+});
+
+export const kibanaRegionMapLayerWizardConfig = {
+ description: i18n.translate('xpack.maps.source.kbnRegionMapDescription', {
+ defaultMessage: 'Vector data from hosted GeoJSON configured in kibana.yml',
+ }),
+ icon: 'logoKibana',
+ renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
+ const onSourceConfigChange = sourceConfig => {
+ const sourceDescriptor = KibanaRegionmapSource.createDescriptor(sourceConfig);
+ const source = new KibanaRegionmapSource(sourceDescriptor, inspectorAdapters);
+ onPreviewSource(source);
+ };
+
+ return ;
+ },
+ title: sourceTitle,
+};
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/kibana_tilemap_source/index.js b/x-pack/legacy/plugins/maps/public/layers/sources/kibana_tilemap_source/index.js
index 3226fb89b700b..9fd7f088032ca 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/kibana_tilemap_source/index.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/kibana_tilemap_source/index.js
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { KibanaTilemapSource } from './kibana_tilemap_source';
+export { KibanaTilemapSource, kibanaBasemapLayerWizardConfig } from './kibana_tilemap_source';
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_tilemap_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_tilemap_source.js
index 21ab2ba42c7bb..b21bb6bdbbad4 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_tilemap_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_tilemap_source.js
@@ -11,17 +11,15 @@ import { getKibanaTileMap } from '../../../meta';
import { i18n } from '@kbn/i18n';
import { getDataSourceLabel } from '../../../../common/i18n_getters';
import _ from 'lodash';
+import { KIBANA_TILEMAP } from '../../../../common/constants';
+import { registerSource } from '../source_registry';
-export class KibanaTilemapSource extends AbstractTMSSource {
- static type = 'KIBANA_TILEMAP';
- static title = i18n.translate('xpack.maps.source.kbnTMSTitle', {
- defaultMessage: 'Configured Tile Map Service',
- });
- static description = i18n.translate('xpack.maps.source.kbnTMSDescription', {
- defaultMessage: 'Tile map service configured in kibana.yml',
- });
+const sourceTitle = i18n.translate('xpack.maps.source.kbnTMSTitle', {
+ defaultMessage: 'Configured Tile Map Service',
+});
- static icon = 'logoKibana';
+export class KibanaTilemapSource extends AbstractTMSSource {
+ static type = KIBANA_TILEMAP;
static createDescriptor() {
return {
@@ -29,20 +27,11 @@ export class KibanaTilemapSource extends AbstractTMSSource {
};
}
- static renderEditor = ({ onPreviewSource, inspectorAdapters }) => {
- const onSourceConfigChange = () => {
- const sourceDescriptor = KibanaTilemapSource.createDescriptor();
- const source = new KibanaTilemapSource(sourceDescriptor, inspectorAdapters);
- onPreviewSource(source);
- };
- return ;
- };
-
async getImmutableProperties() {
return [
{
label: getDataSourceLabel(),
- value: KibanaTilemapSource.title,
+ value: sourceTitle,
},
{
label: i18n.translate('xpack.maps.source.kbnTMS.urlLabel', {
@@ -94,3 +83,24 @@ export class KibanaTilemapSource extends AbstractTMSSource {
}
}
}
+
+registerSource({
+ ConstructorFunction: KibanaTilemapSource,
+ type: KIBANA_TILEMAP,
+});
+
+export const kibanaBasemapLayerWizardConfig = {
+ description: i18n.translate('xpack.maps.source.kbnTMSDescription', {
+ defaultMessage: 'Tile map service configured in kibana.yml',
+ }),
+ icon: 'logoKibana',
+ renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
+ const onSourceConfigChange = () => {
+ const sourceDescriptor = KibanaTilemapSource.createDescriptor();
+ const source = new KibanaTilemapSource(sourceDescriptor, inspectorAdapters);
+ onPreviewSource(source);
+ };
+ return ;
+ },
+ title: sourceTitle,
+};
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/source_registry.ts b/x-pack/legacy/plugins/maps/public/layers/sources/source_registry.ts
new file mode 100644
index 0000000000000..518cab68b601b
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/source_registry.ts
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+/* eslint-disable @typescript-eslint/consistent-type-definitions */
+
+import { AbstractSourceDescriptor } from '../../../common/descriptor_types';
+import { ISource } from './source';
+
+type SourceRegistryEntry = {
+ ConstructorFunction: new (
+ sourceDescriptor: AbstractSourceDescriptor,
+ inspectorAdapters: unknown
+ ) => ISource;
+ type: string;
+};
+
+const registry: SourceRegistryEntry[] = [];
+
+export function registerSource(entry: SourceRegistryEntry) {
+ const sourceTypeExists = registry.some(({ type }: SourceRegistryEntry) => {
+ return entry.type === type;
+ });
+ if (sourceTypeExists) {
+ throw new Error(
+ `Unable to register source type ${entry.type}. ${entry.type} has already been registered`
+ );
+ }
+ registry.push(entry);
+}
+
+export function getSourceByType(sourceType: string): SourceRegistryEntry | undefined {
+ return registry.find((source: SourceRegistryEntry) => source.type === sourceType);
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/wms_source/index.js b/x-pack/legacy/plugins/maps/public/layers/sources/wms_source/index.js
index 22bc50e601f56..daae552a6f772 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/wms_source/index.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/wms_source/index.js
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { WMSSource } from './wms_source';
+export { WMSSource, wmsLayerWizardConfig } from './wms_source';
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/wms_source/wms_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/wms_source/wms_source.js
index 61955df94e451..749560a2bb4b1 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/wms_source/wms_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/wms_source/wms_source.js
@@ -12,16 +12,15 @@ import { WMSCreateSourceEditor } from './wms_create_source_editor';
import { i18n } from '@kbn/i18n';
import { getDataSourceLabel, getUrlLabel } from '../../../../common/i18n_getters';
import { WmsClient } from './wms_client';
+import { WMS } from '../../../../common/constants';
+import { registerSource } from '../source_registry';
+
+const sourceTitle = i18n.translate('xpack.maps.source.wmsTitle', {
+ defaultMessage: 'Web Map Service',
+});
export class WMSSource extends AbstractTMSSource {
- static type = 'WMS';
- static title = i18n.translate('xpack.maps.source.wmsTitle', {
- defaultMessage: 'Web Map Service',
- });
- static description = i18n.translate('xpack.maps.source.wmsDescription', {
- defaultMessage: 'Maps from OGC Standard WMS',
- });
- static icon = 'grid';
+ static type = WMS;
static createDescriptor({ serviceUrl, layers, styles, attributionText, attributionUrl }) {
return {
@@ -34,23 +33,9 @@ export class WMSSource extends AbstractTMSSource {
};
}
- static renderEditor({ onPreviewSource, inspectorAdapters }) {
- const onSourceConfigChange = sourceConfig => {
- if (!sourceConfig) {
- onPreviewSource(null);
- return;
- }
-
- const sourceDescriptor = WMSSource.createDescriptor(sourceConfig);
- const source = new WMSSource(sourceDescriptor, inspectorAdapters);
- onPreviewSource(source);
- };
- return ;
- }
-
async getImmutableProperties() {
return [
- { label: getDataSourceLabel(), value: WMSSource.title },
+ { label: getDataSourceLabel(), value: sourceTitle },
{ label: getUrlLabel(), value: this._descriptor.serviceUrl },
{
label: i18n.translate('xpack.maps.source.wms.layersLabel', {
@@ -104,3 +89,29 @@ export class WMSSource extends AbstractTMSSource {
return client.getUrlTemplate(this._descriptor.layers, this._descriptor.styles || '');
}
}
+
+registerSource({
+ ConstructorFunction: WMSSource,
+ type: WMS,
+});
+
+export const wmsLayerWizardConfig = {
+ description: i18n.translate('xpack.maps.source.wmsDescription', {
+ defaultMessage: 'Maps from OGC Standard WMS',
+ }),
+ icon: 'grid',
+ renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
+ const onSourceConfigChange = sourceConfig => {
+ if (!sourceConfig) {
+ onPreviewSource(null);
+ return;
+ }
+
+ const sourceDescriptor = WMSSource.createDescriptor(sourceConfig);
+ const source = new WMSSource(sourceDescriptor, inspectorAdapters);
+ onPreviewSource(source);
+ };
+ return ;
+ },
+ title: sourceTitle,
+};
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.js
index 354883372e244..d53fbffd21512 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/xyz_tms_source.js
@@ -13,16 +13,14 @@ import { i18n } from '@kbn/i18n';
import { getDataSourceLabel, getUrlLabel } from '../../../common/i18n_getters';
import _ from 'lodash';
import { EMS_XYZ } from '../../../common/constants';
+import { registerSource } from './source_registry';
+
+const sourceTitle = i18n.translate('xpack.maps.source.ems_xyzTitle', {
+ defaultMessage: 'Tile Map Service',
+});
export class XYZTMSSource extends AbstractTMSSource {
static type = EMS_XYZ;
- static title = i18n.translate('xpack.maps.source.ems_xyzTitle', {
- defaultMessage: 'Tile Map Service',
- });
- static description = i18n.translate('xpack.maps.source.ems_xyzDescription', {
- defaultMessage: 'Tile map service configured in interface',
- });
- static icon = 'grid';
static createDescriptor({ urlTemplate, attributionText, attributionUrl }) {
return {
@@ -33,18 +31,9 @@ export class XYZTMSSource extends AbstractTMSSource {
};
}
- static renderEditor({ onPreviewSource, inspectorAdapters }) {
- const onSourceConfigChange = sourceConfig => {
- const sourceDescriptor = XYZTMSSource.createDescriptor(sourceConfig);
- const source = new XYZTMSSource(sourceDescriptor, inspectorAdapters);
- onPreviewSource(source);
- };
- return ;
- }
-
async getImmutableProperties() {
return [
- { label: getDataSourceLabel(), value: XYZTMSSource.title },
+ { label: getDataSourceLabel(), value: sourceTitle },
{ label: getUrlLabel(), value: this._descriptor.urlTemplate },
];
}
@@ -175,3 +164,24 @@ class XYZTMSEditor extends React.Component {
);
}
}
+
+registerSource({
+ ConstructorFunction: XYZTMSSource,
+ type: EMS_XYZ,
+});
+
+export const tmsLayerWizardConfig = {
+ description: i18n.translate('xpack.maps.source.ems_xyzDescription', {
+ defaultMessage: 'Tile map service configured in interface',
+ }),
+ icon: 'grid',
+ renderWizard: ({ onPreviewSource, inspectorAdapters }) => {
+ const onSourceConfigChange = sourceConfig => {
+ const sourceDescriptor = XYZTMSSource.createDescriptor(sourceConfig);
+ const source = new XYZTMSSource(sourceDescriptor, inspectorAdapters);
+ onPreviewSource(source);
+ };
+ return ;
+ },
+ title: sourceTitle,
+};
diff --git a/x-pack/legacy/plugins/maps/public/plugin.ts b/x-pack/legacy/plugins/maps/public/plugin.ts
index 53c951ac787e1..c08ed6fc6da61 100644
--- a/x-pack/legacy/plugins/maps/public/plugin.ts
+++ b/x-pack/legacy/plugins/maps/public/plugin.ts
@@ -4,6 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import './layers/layer_wizard_registry';
+import './layers/sources/source_registry';
+import './layers/load_layer_wizards';
+
import { Plugin, CoreStart, CoreSetup } from 'src/core/public';
// @ts-ignore
import { wrapInI18nContext } from 'ui/i18n';
diff --git a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js
index 61eea2d172ae4..397478cfd1d1b 100644
--- a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js
+++ b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.js
@@ -11,7 +11,6 @@ import { VectorTileLayer } from '../layers/vector_tile_layer';
import { VectorLayer } from '../layers/vector_layer';
import { HeatmapLayer } from '../layers/heatmap_layer';
import { BlendedVectorLayer } from '../layers/blended_vector_layer';
-import { ALL_SOURCES } from '../layers/sources/all_sources';
import { getTimeFilter } from '../kibana_services';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getInspectorAdapters } from '../../../../../plugins/maps/public/reducers/non_serializable_instances';
@@ -21,6 +20,7 @@ import {
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../../plugins/maps/public/reducers/util';
import { InnerJoin } from '../layers/joins/inner_join';
+import { getSourceByType } from '../layers/sources/source_registry';
function createLayerInstance(layerDescriptor, inspectorAdapters) {
const source = createSourceInstance(layerDescriptor.sourceDescriptor, inspectorAdapters);
@@ -49,13 +49,11 @@ function createLayerInstance(layerDescriptor, inspectorAdapters) {
}
function createSourceInstance(sourceDescriptor, inspectorAdapters) {
- const Source = ALL_SOURCES.find(Source => {
- return Source.type === sourceDescriptor.type;
- });
- if (!Source) {
+ const source = getSourceByType(sourceDescriptor.type);
+ if (!source) {
throw new Error(`Unrecognized sourceType ${sourceDescriptor.type}`);
}
- return new Source(sourceDescriptor, inspectorAdapters);
+ return new source.ConstructorFunction(sourceDescriptor, inspectorAdapters);
}
export const getOpenTooltips = ({ map }) => {
diff --git a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js
index e7f071d5729c6..1a5ab633a569f 100644
--- a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js
+++ b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.test.js
@@ -8,7 +8,6 @@ jest.mock('../layers/vector_layer', () => {});
jest.mock('../layers/blended_vector_layer', () => {});
jest.mock('../layers/heatmap_layer', () => {});
jest.mock('../layers/vector_tile_layer', () => {});
-jest.mock('../layers/sources/all_sources', () => {});
jest.mock('../layers/joins/inner_join', () => {});
jest.mock('../../../../../plugins/maps/public/reducers/non_serializable_instances', () => ({
getInspectorAdapters: () => {
diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts
index 30a3350ad754e..bd4406ef5ce63 100644
--- a/x-pack/plugins/maps/common/constants.ts
+++ b/x-pack/plugins/maps/common/constants.ts
@@ -62,6 +62,9 @@ export const ES_GEO_GRID = 'ES_GEO_GRID';
export const ES_SEARCH = 'ES_SEARCH';
export const ES_PEW_PEW = 'ES_PEW_PEW';
export const EMS_XYZ = 'EMS_XYZ'; // identifies a custom TMS source. Name is a little unfortunate.
+export const WMS = 'WMS';
+export const KIBANA_TILEMAP = 'KIBANA_TILEMAP';
+export const REGIONMAP_FILE = 'REGIONMAP_FILE';
export enum FIELD_ORIGIN {
SOURCE = 'source',
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index aea6e2ab00094..1b4810e8fdf0a 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -7137,12 +7137,10 @@
"xpack.maps.source.esGeoGrid.geofieldLabel": "地理空間フィールド",
"xpack.maps.source.esGeoGrid.geofieldPlaceholder": "ジオフィールドを選択",
"xpack.maps.source.esGeoGrid.gridRectangleDropdownOption": "グリッド四角",
- "xpack.maps.source.esGeoGrid.heatmapDropdownOption": "ヒートマップ",
"xpack.maps.source.esGeoGrid.indexPatternLabel": "インデックスパターン",
"xpack.maps.source.esGeoGrid.indexPatternPlaceholder": "インデックスパターンを選択",
"xpack.maps.source.esGeoGrid.pointsDropdownOption": "点",
"xpack.maps.source.esGeoGrid.showAsLabel": "表示形式",
- "xpack.maps.source.esGeoGrid.showAsPlaceholder": "1 つのオプションを選択",
"xpack.maps.source.esGrid.coarseDropdownOption": "粗い",
"xpack.maps.source.esGrid.fineDropdownOption": "細かい",
"xpack.maps.source.esGrid.finestDropdownOption": "最も細かい",
@@ -7151,9 +7149,6 @@
"xpack.maps.source.esGrid.metricsLabel": "メトリック",
"xpack.maps.source.esGrid.noIndexPatternErrorMessage": "インデックスパターン {id} が見つかりません",
"xpack.maps.source.esGrid.resolutionParamErrorMessage": "グリッド解像度パラメーターが認識されません: {resolution}",
- "xpack.maps.source.esGrid.showasFieldLabel": "表示形式",
- "xpack.maps.source.esGridDescription": "それぞれのグリッド付きセルのメトリックでグリッドにグループ分けされた地理空間データです。",
- "xpack.maps.source.esGridTitle": "グリッド集約",
"xpack.maps.source.esSearch.convertToGeoJsonErrorMsg": "検索への応答を geoJson 機能コレクションに変換できません。エラー: {errorMsg}",
"xpack.maps.source.esSearch.extentFilterLabel": "マップの表示範囲でデータを動的にフィルタリング",
"xpack.maps.source.esSearch.geofieldLabel": "地理空間フィールド",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index dfc5ef065732e..5b3baa3552dbe 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -7137,12 +7137,10 @@
"xpack.maps.source.esGeoGrid.geofieldLabel": "地理空间字段",
"xpack.maps.source.esGeoGrid.geofieldPlaceholder": "选择地理字段",
"xpack.maps.source.esGeoGrid.gridRectangleDropdownOption": "网格矩形",
- "xpack.maps.source.esGeoGrid.heatmapDropdownOption": "热图",
"xpack.maps.source.esGeoGrid.indexPatternLabel": "索引模式",
"xpack.maps.source.esGeoGrid.indexPatternPlaceholder": "选择索引模式",
"xpack.maps.source.esGeoGrid.pointsDropdownOption": "磅",
"xpack.maps.source.esGeoGrid.showAsLabel": "显示为",
- "xpack.maps.source.esGeoGrid.showAsPlaceholder": "选择单个选项",
"xpack.maps.source.esGrid.coarseDropdownOption": "粗糙",
"xpack.maps.source.esGrid.fineDropdownOption": "精致",
"xpack.maps.source.esGrid.finestDropdownOption": "最精致化",
@@ -7151,9 +7149,6 @@
"xpack.maps.source.esGrid.metricsLabel": "指标",
"xpack.maps.source.esGrid.noIndexPatternErrorMessage": "找不到索引模式 {id}",
"xpack.maps.source.esGrid.resolutionParamErrorMessage": "无法识别网格分辨率参数:{resolution}",
- "xpack.maps.source.esGrid.showasFieldLabel": "显示为",
- "xpack.maps.source.esGridDescription": "地理空间数据在网格中进行分组,每个网格单元格都具有指标",
- "xpack.maps.source.esGridTitle": "网格聚合",
"xpack.maps.source.esSearch.convertToGeoJsonErrorMsg": "无法将搜索响应转换成 geoJson 功能集合,错误:{errorMsg}",
"xpack.maps.source.esSearch.extentFilterLabel": "在可见地图区域中动态筛留数据",
"xpack.maps.source.esSearch.geofieldLabel": "地理空间字段",
diff --git a/x-pack/test/functional/page_objects/gis_page.js b/x-pack/test/functional/page_objects/gis_page.js
index f8d1808c1ef8d..700575220297e 100644
--- a/x-pack/test/functional/page_objects/gis_page.js
+++ b/x-pack/test/functional/page_objects/gis_page.js
@@ -511,7 +511,7 @@ export function GisPageProvider({ getService, getPageObjects }) {
async selectGeoJsonUploadSource() {
log.debug(`Select upload geojson source`);
- await testSubjects.click('uploadedGeoJson');
+ await testSubjects.click('uploadGeoJson');
}
async uploadJsonFileForIndexing(path) {
From df655c9a97a810639a24f12f64cd48b70396ffc8 Mon Sep 17 00:00:00 2001
From: Shahzad
Date: Thu, 2 Apr 2020 08:31:32 +0200
Subject: [PATCH 07/99] [Uptime] Optimize get latest monitor API (#61820)
* update monitor status API
* update fixture
* fix types
* fix tets
* fix tests
---
.../uptime/common/constants/rest_api.ts | 1 -
.../monitor/status_bar_container.tsx | 12 +-
.../__snapshots__/monitor.test.tsx.snap | 2 +-
.../plugins/uptime/public/pages/monitor.tsx | 54 ++-------
.../public/state/actions/monitor_status.ts | 4 -
.../uptime/public/state/api/monitor_status.ts | 14 +--
.../public/state/effects/monitor_status.ts | 14 +--
.../public/state/reducers/monitor_status.ts | 37 ++----
.../state/selectors/__tests__/index.test.ts | 1 -
.../uptime/public/state/selectors/index.ts | 4 +-
.../__tests__/get_latest_monitor.test.ts | 51 +++-----
.../server/lib/requests/get_latest_monitor.ts | 31 ++---
.../uptime/server/lib/requests/get_monitor.ts | 49 --------
.../uptime/server/lib/requests/index.ts | 1 -
.../server/lib/requests/uptime_requests.ts | 2 -
.../plugins/uptime/server/rest_api/index.ts | 2 -
.../uptime/server/rest_api/monitors/index.ts | 2 +-
.../uptime/server/rest_api/monitors/status.ts | 25 +---
.../rest/fixtures/monitor_latest_status.json | 114 +++++-------------
.../rest/fixtures/selected_monitor.json | 28 -----
.../api_integration/apis/uptime/rest/index.ts | 1 -
.../apis/uptime/rest/selected_monitor.ts | 23 ----
22 files changed, 78 insertions(+), 394 deletions(-)
delete mode 100644 x-pack/plugins/uptime/server/lib/requests/get_monitor.ts
delete mode 100644 x-pack/test/api_integration/apis/uptime/rest/fixtures/selected_monitor.json
delete mode 100644 x-pack/test/api_integration/apis/uptime/rest/selected_monitor.ts
diff --git a/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts b/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts
index 7fafe6584d831..86e2b03e13f22 100644
--- a/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts
+++ b/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts
@@ -10,7 +10,6 @@ export enum API_URLS {
MONITOR_LOCATIONS = `/api/uptime/monitor/locations`,
MONITOR_DURATION = `/api/uptime/monitor/duration`,
MONITOR_DETAILS = `/api/uptime/monitor/details`,
- MONITOR_SELECTED = `/api/uptime/monitor/selected`,
MONITOR_STATUS = `/api/uptime/monitor/status`,
PINGS = '/api/uptime/pings',
PING_HISTOGRAM = `/api/uptime/ping/histogram`,
diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx
index 9e7834ae6f242..dd6f7a89cf9a3 100644
--- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx
@@ -8,9 +8,9 @@ import React, { useContext, useEffect } from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { AppState } from '../../../state';
-import { monitorLocationsSelector, selectMonitorStatus } from '../../../state/selectors';
+import { monitorLocationsSelector, monitorStatusSelector } from '../../../state/selectors';
import { MonitorStatusBarComponent } from '../../functional/monitor_status_details/monitor_status_bar';
-import { getMonitorStatusAction, getSelectedMonitorAction } from '../../../state/actions';
+import { getMonitorStatusAction } from '../../../state/actions';
import { useUrlParams } from '../../../hooks';
import { Ping } from '../../../../common/graphql/types';
import { MonitorLocations } from '../../../../common/runtime_types/monitor';
@@ -23,7 +23,6 @@ interface StateProps {
interface DispatchProps {
loadMonitorStatus: typeof getMonitorStatusAction;
- loadSelectedMonitor: typeof getSelectedMonitorAction;
}
interface OwnProps {
@@ -34,7 +33,6 @@ type Props = OwnProps & StateProps & DispatchProps;
const Container: React.FC = ({
loadMonitorStatus,
- loadSelectedMonitor,
monitorId,
monitorStatus,
monitorLocations,
@@ -46,8 +44,7 @@ const Container: React.FC = ({
useEffect(() => {
loadMonitorStatus({ dateStart, dateEnd, monitorId });
- loadSelectedMonitor({ monitorId });
- }, [monitorId, dateStart, dateEnd, loadMonitorStatus, lastRefresh, loadSelectedMonitor]);
+ }, [monitorId, dateStart, dateEnd, loadMonitorStatus, lastRefresh]);
return (
= ({
};
const mapStateToProps = (state: AppState, ownProps: OwnProps) => ({
- monitorStatus: selectMonitorStatus(state),
+ monitorStatus: monitorStatusSelector(state),
monitorLocations: monitorLocationsSelector(state, ownProps.monitorId),
});
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({
- loadSelectedMonitor: params => dispatch(getSelectedMonitorAction(params)),
loadMonitorStatus: params => dispatch(getMonitorStatusAction(params)),
});
diff --git a/x-pack/legacy/plugins/uptime/public/pages/__tests__/__snapshots__/monitor.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/pages/__tests__/__snapshots__/monitor.test.tsx.snap
index f637af397bbeb..6064caa868bf8 100644
--- a/x-pack/legacy/plugins/uptime/public/pages/__tests__/__snapshots__/monitor.test.tsx.snap
+++ b/x-pack/legacy/plugins/uptime/public/pages/__tests__/__snapshots__/monitor.test.tsx.snap
@@ -51,6 +51,6 @@ exports[`MonitorPage shallow renders expected elements for valid props 1`] = `
}
}
>
-
+
`;
diff --git a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx
index 3de636cac6ecd..21124b7323d68 100644
--- a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx
+++ b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx
@@ -5,45 +5,23 @@
*/
import { EuiSpacer } from '@elastic/eui';
-import React, { useContext, useState, useEffect } from 'react';
+import React, { useContext, useState } from 'react';
import { useParams } from 'react-router-dom';
-import { connect, MapDispatchToPropsFunction, MapStateToPropsParam } from 'react-redux';
+import { useSelector } from 'react-redux';
import { MonitorCharts, PingList } from '../components/functional';
import { UptimeRefreshContext } from '../contexts';
import { useUptimeTelemetry, useUrlParams, UptimePage } from '../hooks';
import { useTrackPageview } from '../../../../../plugins/observability/public';
import { MonitorStatusDetails } from '../components/connected';
-import { Ping } from '../../common/graphql/types';
-import { AppState } from '../state';
-import { selectSelectedMonitor } from '../state/selectors';
-import { getSelectedMonitorAction } from '../state/actions';
+import { monitorStatusSelector } from '../state/selectors';
import { PageHeader } from './page_header';
import { useBreadcrumbs } from '../hooks/use_breadcrumbs';
-interface StateProps {
- selectedMonitor: Ping | null;
-}
-
-interface DispatchProps {
- dispatchGetMonitorStatus: (monitorId: string) => void;
-}
-
-type Props = StateProps & DispatchProps;
-
-export const MonitorPageComponent: React.FC = ({
- selectedMonitor,
- dispatchGetMonitorStatus,
-}: Props) => {
+export const MonitorPage: React.FC = () => {
// decode 64 base string, it was decoded to make it a valid url, since monitor id can be a url
let { monitorId } = useParams();
monitorId = atob(monitorId || '');
- useEffect(() => {
- if (monitorId) {
- dispatchGetMonitorStatus(monitorId);
- }
- }, [dispatchGetMonitorStatus, monitorId]);
-
const [pingListPageCount, setPingListPageCount] = useState(10);
const { refreshApp } = useContext(UptimeRefreshContext);
const [getUrlParams, updateUrlParams] = useUrlParams();
@@ -53,11 +31,13 @@ export const MonitorPageComponent: React.FC = ({
const [selectedLocation, setSelectedLocation] = useState(undefined);
const [pingListIndex, setPingListIndex] = useState(0);
+ const selectedMonitor = useSelector(monitorStatusSelector);
+
const sharedVariables = {
dateRangeStart,
dateRangeEnd,
- location: selectedLocation,
monitorId,
+ location: selectedLocation,
};
useUptimeTelemetry(UptimePage.Monitor);
@@ -65,7 +45,7 @@ export const MonitorPageComponent: React.FC = ({
useTrackPageview({ app: 'uptime', path: 'monitor' });
useTrackPageview({ app: 'uptime', path: 'monitor', delay: 15000 });
- const nameOrId = selectedMonitor?.monitor?.name || selectedMonitor?.monitor?.id || '';
+ const nameOrId = selectedMonitor?.monitor?.name || monitorId || '';
useBreadcrumbs([{ text: nameOrId }]);
return (
<>
@@ -97,21 +77,3 @@ export const MonitorPageComponent: React.FC = ({
>
);
};
-
-const mapStateToProps: MapStateToPropsParam = state => ({
- selectedMonitor: selectSelectedMonitor(state),
-});
-
-const mapDispatchToProps: MapDispatchToPropsFunction = (dispatch, own) => {
- return {
- dispatchGetMonitorStatus: (monitorId: string) => {
- dispatch(
- getSelectedMonitorAction({
- monitorId,
- })
- );
- },
- };
-};
-
-export const MonitorPage = connect(mapStateToProps, mapDispatchToProps)(MonitorPageComponent);
diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts
index 7917628abf7da..a8f37d38ebae6 100644
--- a/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts
@@ -7,10 +7,6 @@ import { createAction } from 'redux-actions';
import { QueryParams } from './types';
import { Ping } from '../../../common/graphql/types';
-export const getSelectedMonitorAction = createAction<{ monitorId: string }>('GET_SELECTED_MONITOR');
-export const getSelectedMonitorActionSuccess = createAction('GET_SELECTED_MONITOR_SUCCESS');
-export const getSelectedMonitorActionFail = createAction('GET_SELECTED_MONITOR_FAIL');
-
export const getMonitorStatusAction = createAction('GET_MONITOR_STATUS');
export const getMonitorStatusActionSuccess = createAction('GET_MONITOR_STATUS_SUCCESS');
export const getMonitorStatusActionFail = createAction('GET_MONITOR_STATUS_FAIL');
diff --git a/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts
index 0f7608ba57ea7..f9e171adda334 100644
--- a/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts
@@ -7,19 +7,7 @@
import { QueryParams } from '../actions/types';
import { Ping } from '../../../common/graphql/types';
import { apiService } from './utils';
-import { API_URLS } from '../../../common/constants/rest_api';
-
-export interface APIParams {
- monitorId: string;
-}
-
-export const fetchSelectedMonitor = async ({ monitorId }: APIParams): Promise => {
- const queryParams = {
- monitorId,
- };
-
- return await apiService.get(API_URLS.MONITOR_SELECTED, queryParams);
-};
+import { API_URLS } from '../../../common/constants';
export const fetchMonitorStatus = async ({
monitorId,
diff --git a/x-pack/legacy/plugins/uptime/public/state/effects/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/effects/monitor_status.ts
index 1207ab20bc711..2669629ed34f5 100644
--- a/x-pack/legacy/plugins/uptime/public/state/effects/monitor_status.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/effects/monitor_status.ts
@@ -6,14 +6,11 @@
import { takeLatest } from 'redux-saga/effects';
import {
- getSelectedMonitorAction,
- getSelectedMonitorActionSuccess,
- getSelectedMonitorActionFail,
getMonitorStatusAction,
getMonitorStatusActionSuccess,
getMonitorStatusActionFail,
} from '../actions';
-import { fetchSelectedMonitor, fetchMonitorStatus } from '../api';
+import { fetchMonitorStatus } from '../api';
import { fetchEffectFactory } from './fetch_effect';
export function* fetchMonitorStatusEffect() {
@@ -25,13 +22,4 @@ export function* fetchMonitorStatusEffect() {
getMonitorStatusActionFail
)
);
-
- yield takeLatest(
- getSelectedMonitorAction,
- fetchEffectFactory(
- fetchSelectedMonitor,
- getSelectedMonitorActionSuccess,
- getSelectedMonitorActionFail
- )
- );
}
diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts
index c2dfbd7f90ff2..6cfaa9f8f59c1 100644
--- a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts
@@ -5,9 +5,6 @@
*/
import { handleActions, Action } from 'redux-actions';
import {
- getSelectedMonitorAction,
- getSelectedMonitorActionSuccess,
- getSelectedMonitorActionFail,
getMonitorStatusAction,
getMonitorStatusActionSuccess,
getMonitorStatusActionFail,
@@ -17,13 +14,11 @@ import { QueryParams } from '../actions/types';
export interface MonitorStatusState {
status: Ping | null;
- monitor: Ping | null;
loading: boolean;
}
const initialState: MonitorStatusState = {
status: null,
- monitor: null,
loading: false,
};
@@ -31,32 +26,22 @@ type MonitorStatusPayload = QueryParams & Ping;
export const monitorStatusReducer = handleActions(
{
- [String(getSelectedMonitorAction)]: (state, action: Action) => ({
- ...state,
- loading: true,
- }),
-
- [String(getSelectedMonitorActionSuccess)]: (state, action: Action) => ({
- ...state,
- loading: false,
- monitor: { ...action.payload } as Ping,
- }),
-
- [String(getSelectedMonitorActionFail)]: (state, action: Action) => ({
- ...state,
- loading: false,
- }),
-
[String(getMonitorStatusAction)]: (state, action: Action) => ({
...state,
loading: true,
}),
- [String(getMonitorStatusActionSuccess)]: (state, action: Action) => ({
- ...state,
- loading: false,
- status: { ...action.payload } as Ping,
- }),
+ [String(getMonitorStatusActionSuccess)]: (state, action: Action) => {
+ return {
+ ...state,
+ loading: false,
+ // Keeping url from prev request to display, if there is no latest status
+ status: {
+ url: action.payload?.url || state.status?.url,
+ ...action.payload,
+ } as Ping,
+ };
+ },
[String(getMonitorStatusActionFail)]: (state, action: Action) => ({
...state,
diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts
index 573d5b1906082..3b4547514a11e 100644
--- a/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts
@@ -46,7 +46,6 @@ describe('state selectors', () => {
},
monitorStatus: {
status: null,
- monitor: null,
loading: false,
},
indexPattern: {
diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts
index 21e01bd7d8279..0fc3c7151cb3b 100644
--- a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts
@@ -22,9 +22,7 @@ export const monitorLocationsSelector = (state: AppState, monitorId: string) =>
return state.monitor.monitorLocationsList?.get(monitorId);
};
-export const selectSelectedMonitor = (state: AppState) => state.monitorStatus.monitor;
-
-export const selectMonitorStatus = (state: AppState) => state.monitorStatus.status;
+export const monitorStatusSelector = (state: AppState) => state.monitorStatus.status;
export const selectDynamicSettings = (state: AppState) => {
return state.dynamicSettings;
diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts
index b7e340fddbd2c..112c8e97d4c00 100644
--- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts
@@ -31,49 +31,25 @@ describe('getLatestMonitor', () => {
],
},
},
- aggs: {
- by_id: {
- terms: {
- field: 'monitor.id',
- size: 1000,
- },
- aggs: {
- latest: {
- top_hits: {
- size: 1,
- sort: {
- '@timestamp': { order: 'desc' },
- },
- },
- },
- },
- },
+ size: 1,
+ _source: ['url', 'monitor', 'observer', 'tls', '@timestamp'],
+ sort: {
+ '@timestamp': { order: 'desc' },
},
- size: 0,
},
};
mockEsSearchResult = {
- aggregations: {
- by_id: {
- buckets: [
- {
- latest: {
- hits: {
- hits: [
- {
- _source: {
- '@timestamp': 123456,
- monitor: {
- id: 'testMonitor',
- },
- },
- },
- ],
- },
+ hits: {
+ hits: [
+ {
+ _source: {
+ timestamp: 123456,
+ monitor: {
+ id: 'testMonitor',
},
},
- ],
- },
+ },
+ ],
},
};
});
@@ -87,6 +63,7 @@ describe('getLatestMonitor', () => {
dateEnd: 'now',
monitorId: 'testMonitor',
});
+
expect(result.timestamp).toBe(123456);
expect(result.monitor).not.toBeFalsy();
expect(result?.monitor?.id).toBe('testMonitor');
diff --git a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts
index 176963a998685..299e3eb6ca3cf 100644
--- a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts
@@ -26,8 +26,6 @@ export const getLatestMonitor: UMElasticsearchQueryFn {
- // TODO: Write tests for this function
-
const params = {
index: dynamicSettings.heartbeatIndices,
body: {
@@ -46,33 +44,20 @@ export const getLatestMonitor: UMElasticsearchQueryFn = async ({
- callES,
- dynamicSettings,
- monitorId,
-}) => {
- const params = {
- index: dynamicSettings.heartbeatIndices,
- body: {
- size: 1,
- _source: ['url', 'monitor', 'observer'],
- query: {
- bool: {
- filter: [
- {
- term: {
- 'monitor.id': monitorId,
- },
- },
- ],
- },
- },
- sort: [
- {
- '@timestamp': {
- order: 'desc',
- },
- },
- ],
- },
- };
-
- const result = await callES('search', params);
-
- return result.hits.hits[0]?._source;
-};
diff --git a/x-pack/plugins/uptime/server/lib/requests/index.ts b/x-pack/plugins/uptime/server/lib/requests/index.ts
index 7225d329d3c7f..445adc3c15a93 100644
--- a/x-pack/plugins/uptime/server/lib/requests/index.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/index.ts
@@ -7,7 +7,6 @@
export { getFilterBar, GetFilterBarParams } from './get_filter_bar';
export { getUptimeIndexPattern as getIndexPattern } from './get_index_pattern';
export { getLatestMonitor, GetLatestMonitorParams } from './get_latest_monitor';
-export { getMonitor, GetMonitorParams } from './get_monitor';
export { getMonitorDurationChart, GetMonitorChartsParams } from './get_monitor_duration';
export { getMonitorDetails, GetMonitorDetailsParams } from './get_monitor_details';
export { getMonitorLocations, GetMonitorLocationsParams } from './get_monitor_locations';
diff --git a/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts b/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts
index 6eeea5ba4c3e9..9d3fa5aa08aed 100644
--- a/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts
@@ -9,7 +9,6 @@ import { Ping, PingResults } from '../../../../../legacy/plugins/uptime/common/g
import {
GetFilterBarParams,
GetLatestMonitorParams,
- GetMonitorParams,
GetMonitorChartsParams,
GetMonitorDetailsParams,
GetMonitorLocationsParams,
@@ -39,7 +38,6 @@ export interface UptimeRequests {
getFilterBar: ESQ;
getIndexPattern: ESQ<{}, {}>;
getLatestMonitor: ESQ;
- getMonitor: ESQ;
getMonitorDurationChart: ESQ;
getMonitorDetails: ESQ;
getMonitorLocations: ESQ;
diff --git a/x-pack/plugins/uptime/server/rest_api/index.ts b/x-pack/plugins/uptime/server/rest_api/index.ts
index 561997c3567d0..c84ea71037953 100644
--- a/x-pack/plugins/uptime/server/rest_api/index.ts
+++ b/x-pack/plugins/uptime/server/rest_api/index.ts
@@ -11,7 +11,6 @@ import { createLogPageViewRoute } from './telemetry';
import { createGetSnapshotCount } from './snapshot';
import { UMRestApiRouteFactory } from './types';
import {
- createGetMonitorRoute,
createGetMonitorDetailsRoute,
createGetMonitorLocationsRoute,
createGetStatusBarRoute,
@@ -31,7 +30,6 @@ export const restApiRoutes: UMRestApiRouteFactory[] = [
createGetIndexStatusRoute,
createGetDynamicSettingsRoute,
createPostDynamicSettingsRoute,
- createGetMonitorRoute,
createGetMonitorDetailsRoute,
createGetMonitorLocationsRoute,
createGetStatusBarRoute,
diff --git a/x-pack/plugins/uptime/server/rest_api/monitors/index.ts b/x-pack/plugins/uptime/server/rest_api/monitors/index.ts
index 7f1f10081dc4e..7da717b50c149 100644
--- a/x-pack/plugins/uptime/server/rest_api/monitors/index.ts
+++ b/x-pack/plugins/uptime/server/rest_api/monitors/index.ts
@@ -6,4 +6,4 @@
export { createGetMonitorDetailsRoute } from './monitors_details';
export { createGetMonitorLocationsRoute } from './monitor_locations';
-export { createGetMonitorRoute, createGetStatusBarRoute } from './status';
+export { createGetStatusBarRoute } from './status';
diff --git a/x-pack/plugins/uptime/server/rest_api/monitors/status.ts b/x-pack/plugins/uptime/server/rest_api/monitors/status.ts
index e1fcaf54f2824..9bccd64c4bd65 100644
--- a/x-pack/plugins/uptime/server/rest_api/monitors/status.ts
+++ b/x-pack/plugins/uptime/server/rest_api/monitors/status.ts
@@ -7,30 +7,7 @@
import { schema } from '@kbn/config-schema';
import { UMServerLibs } from '../../lib/lib';
import { UMRestApiRouteFactory } from '../types';
-import { API_URLS } from '../../../../../legacy/plugins/uptime/common/constants/rest_api';
-
-export const createGetMonitorRoute: UMRestApiRouteFactory = (libs: UMServerLibs) => ({
- method: 'GET',
- path: API_URLS.MONITOR_SELECTED,
-
- validate: {
- query: schema.object({
- monitorId: schema.string(),
- }),
- },
- options: {
- tags: ['access:uptime-read'],
- },
- handler: async ({ callES, dynamicSettings }, _context, request, response): Promise => {
- const { monitorId } = request.query;
-
- return response.ok({
- body: {
- ...(await libs.requests.getMonitor({ callES, dynamicSettings, monitorId })),
- },
- });
- },
-});
+import { API_URLS } from '../../../../../legacy/plugins/uptime/common/constants';
export const createGetStatusBarRoute: UMRestApiRouteFactory = (libs: UMServerLibs) => ({
method: 'GET',
diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json
index 1702cb2c21007..5d41cdf611824 100644
--- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json
+++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json
@@ -1,89 +1,29 @@
{
- "@timestamp": "2019-09-11T03:40:34.371Z",
- "agent": {
- "ephemeral_id": "412a92a8-2142-4b1a-a7a2-1afd32e12f85",
- "hostname": "avc-x1x",
- "id": "04e1d082-65bc-4929-8d65-d0768a2621c4",
- "type": "heartbeat",
- "version": "8.0.0"
- },
- "ecs": {
- "version": "1.1.0"
- },
- "event": {
- "dataset": "uptime"
- },
- "host": {
- "name": "avc-x1x"
- },
- "http": {
- "response": {
- "body": {
- "bytes": 3,
- "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf"
- },
- "status_code": 200
- },
- "rtt": {
- "content": {
- "us": 57
- },
- "response_header": {
- "us": 262
- },
- "total": {
- "us": 20331
- },
- "validate": {
- "us": 319
- },
- "write_request": {
- "us": 82
- }
- }
- },
- "monitor": {
- "check_group": "d76f0762-d445-11e9-88e3-3e80641b9c71",
- "duration": {
- "us": 24627
- },
- "id": "0002-up",
- "ip": "127.0.0.1",
- "name": "",
- "status": "up",
- "type": "http"
- },
- "observer": {
- "geo": {
- "location": "37.926868, -78.024902",
- "name": "mpls"
- },
- "hostname": "avc-x1x"
- },
- "resolve": {
- "ip": "127.0.0.1",
- "rtt": {
- "us": 4218
- }
- },
- "summary": {
- "down": 0,
- "up": 1
- },
- "tcp": {
- "rtt": {
- "connect": {
- "us": 103
- }
- }
- },
- "timestamp": "2019-09-11T03:40:34.371Z",
- "url": {
- "domain": "localhost",
- "full": "http://localhost:5678/pattern?r=200x1",
- "path": "/pattern",
- "port": 5678,
- "query": "r=200x1",
- "scheme": "http"
- }
+ "timestamp": "2019-09-11T03:40:34.371Z",
+ "observer": {
+ "geo": {
+ "name": "mpls",
+ "location": "37.926868, -78.024902"
+ },
+ "hostname": "avc-x1x"
+ },
+ "monitor": {
+ "duration": {
+ "us": 24627
+ },
+ "ip": "127.0.0.1",
+ "name": "",
+ "check_group": "d76f0762-d445-11e9-88e3-3e80641b9c71",
+ "id": "0002-up",
+ "type": "http",
+ "status": "up"
+ },
+ "url": {
+ "path": "/pattern",
+ "scheme": "http",
+ "port": 5678,
+ "domain": "localhost",
+ "query": "r=200x1",
+ "full": "http://localhost:5678/pattern?r=200x1"
}
+}
\ No newline at end of file
diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/selected_monitor.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/selected_monitor.json
deleted file mode 100644
index d8367ea67052f..0000000000000
--- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/selected_monitor.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "monitor": {
- "check_group": "d76f0762-d445-11e9-88e3-3e80641b9c71",
- "duration": {
- "us": 24627
- },
- "id": "0002-up",
- "ip": "127.0.0.1",
- "name": "",
- "status": "up",
- "type": "http"
- },
- "observer": {
- "geo": {
- "location": "37.926868, -78.024902",
- "name": "mpls"
- },
- "hostname": "avc-x1x"
- },
- "url": {
- "domain": "localhost",
- "full": "http://localhost:5678/pattern?r=200x1",
- "path": "/pattern",
- "port": 5678,
- "query": "r=200x1",
- "scheme": "http"
- }
-}
diff --git a/x-pack/test/api_integration/apis/uptime/rest/index.ts b/x-pack/test/api_integration/apis/uptime/rest/index.ts
index b2236e1bb6308..f89bec589847e 100644
--- a/x-pack/test/api_integration/apis/uptime/rest/index.ts
+++ b/x-pack/test/api_integration/apis/uptime/rest/index.ts
@@ -47,7 +47,6 @@ export default function({ getService, loadTestFile }: FtrProviderContext) {
before('load heartbeat data', async () => await esArchiver.load('uptime/full_heartbeat'));
after('unload', async () => await esArchiver.unload('uptime/full_heartbeat'));
loadTestFile(require.resolve('./monitor_latest_status'));
- loadTestFile(require.resolve('./selected_monitor'));
loadTestFile(require.resolve('./ping_histogram'));
loadTestFile(require.resolve('./monitor_duration'));
loadTestFile(require.resolve('./doc_count'));
diff --git a/x-pack/test/api_integration/apis/uptime/rest/selected_monitor.ts b/x-pack/test/api_integration/apis/uptime/rest/selected_monitor.ts
deleted file mode 100644
index ed034f58a5f59..0000000000000
--- a/x-pack/test/api_integration/apis/uptime/rest/selected_monitor.ts
+++ /dev/null
@@ -1,23 +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 { expectFixtureEql } from '../graphql/helpers/expect_fixture_eql';
-import { FtrProviderContext } from '../../../ftr_provider_context';
-
-export default function({ getService }: FtrProviderContext) {
- describe('get selected monitor by ID', () => {
- const monitorId = '0002-up';
-
- const supertest = getService('supertest');
-
- it('returns the monitor for give ID', async () => {
- const apiResponse = await supertest.get(
- `/api/uptime/monitor/selected?monitorId=${monitorId}`
- );
- expectFixtureEql(apiResponse.body, 'selected_monitor');
- });
- });
-}
From a9be92b0bf2d18ef2c551059be80bf5b05622a64 Mon Sep 17 00:00:00 2001
From: Vadim Dalecky
Date: Thu, 2 Apr 2020 09:18:40 +0200
Subject: [PATCH 08/99] ci: remove AppArch label from ProBot path-labeler
(#62211)
---
.github/paths-labeller.yml | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/.github/paths-labeller.yml b/.github/paths-labeller.yml
index 4a498af6b1c88..3d35cd74e0718 100644
--- a/.github/paths-labeller.yml
+++ b/.github/paths-labeller.yml
@@ -1,13 +1,4 @@
---
- - "Team:AppArch":
- - "src/plugins/bfetch/**/*.*"
- - "src/plugins/dashboard_embeddable_container/**/*.*"
- - "src/plugins/data/**/*.*"
- - "src/plugins/embeddable/**/*.*"
- - "src/plugins/expressions/**/*.*"
- - "src/plugins/inspector/**/*.*"
- - "src/plugins/ui_actions/**/*.*"
- - "src/plugins/visualizations/**/*.*"
- "Feature:Embedding":
- "src/plugins/embeddable/**/*.*"
- "src/plugins/dashboard_embeddable_container/**/*.*"
From ee3f5309f8ce8de9a6679b2b0331015e918273e6 Mon Sep 17 00:00:00 2001
From: Marta Bondyra
Date: Thu, 2 Apr 2020 09:26:23 +0200
Subject: [PATCH 09/99] [Lens] fix error for minInterval>computedInterval for
XYChart (#61931)
---
.../xy_visualization/xy_expression.test.tsx | 310 ++++++++++++++----
.../public/xy_visualization/xy_expression.tsx | 9 +-
2 files changed, 251 insertions(+), 68 deletions(-)
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx
index cdc5fc2ff1c17..54abc2c2bb667 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx
@@ -18,6 +18,10 @@ import {
} from '@elastic/charts';
import { xyChart, XYChart } from './xy_expression';
import { LensMultiTable } from '../types';
+import {
+ KibanaDatatable,
+ KibanaDatatableRow,
+} from '../../../../../../src/plugins/expressions/public';
import React from 'react';
import { shallow } from 'enzyme';
import { XYArgs, LegendConfig, legendConfig, layerConfig, LayerArgs } from './types';
@@ -26,57 +30,61 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers';
const executeTriggerActions = jest.fn();
+const createSampleDatatableWithRows = (rows: KibanaDatatableRow[]): KibanaDatatable => ({
+ type: 'kibana_datatable',
+ columns: [
+ {
+ id: 'a',
+ name: 'a',
+ formatHint: { id: 'number', params: { pattern: '0,0.000' } },
+ },
+ { id: 'b', name: 'b', formatHint: { id: 'number', params: { pattern: '000,0' } } },
+ {
+ id: 'c',
+ name: 'c',
+ formatHint: { id: 'string' },
+ meta: { type: 'date-histogram', aggConfigParams: { interval: '10s' } },
+ },
+ { id: 'd', name: 'ColD', formatHint: { id: 'string' } },
+ ],
+ rows,
+});
+
+const sampleLayer: LayerArgs = {
+ layerId: 'first',
+ seriesType: 'line',
+ xAccessor: 'c',
+ accessors: ['a', 'b'],
+ splitAccessor: 'd',
+ columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
+ xScaleType: 'ordinal',
+ yScaleType: 'linear',
+ isHistogram: false,
+};
+
+const createArgsWithLayers = (layers: LayerArgs[] = [sampleLayer]): XYArgs => ({
+ xTitle: '',
+ yTitle: '',
+ legend: {
+ type: 'lens_xy_legendConfig',
+ isVisible: false,
+ position: Position.Top,
+ },
+ layers,
+});
+
function sampleArgs() {
const data: LensMultiTable = {
type: 'lens_multitable',
tables: {
- first: {
- type: 'kibana_datatable',
- columns: [
- {
- id: 'a',
- name: 'a',
- formatHint: { id: 'number', params: { pattern: '0,0.000' } },
- },
- { id: 'b', name: 'b', formatHint: { id: 'number', params: { pattern: '000,0' } } },
- {
- id: 'c',
- name: 'c',
- formatHint: { id: 'string' },
- meta: { type: 'date-histogram', aggConfigParams: { interval: '10s' } },
- },
- { id: 'd', name: 'ColD', formatHint: { id: 'string' } },
- ],
- rows: [
- { a: 1, b: 2, c: 'I', d: 'Foo' },
- { a: 1, b: 5, c: 'J', d: 'Bar' },
- ],
- },
+ first: createSampleDatatableWithRows([
+ { a: 1, b: 2, c: 'I', d: 'Foo' },
+ { a: 1, b: 5, c: 'J', d: 'Bar' },
+ ]),
},
};
- const args: XYArgs = {
- xTitle: '',
- yTitle: '',
- legend: {
- type: 'lens_xy_legendConfig',
- isVisible: false,
- position: Position.Top,
- },
- layers: [
- {
- layerId: 'first',
- seriesType: 'line',
- xAccessor: 'c',
- accessors: ['a', 'b'],
- splitAccessor: 'd',
- columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
- xScaleType: 'ordinal',
- yScaleType: 'linear',
- isHistogram: false,
- },
- ],
- };
+ const args: XYArgs = createArgsWithLayers();
return { data, args };
}
@@ -158,35 +166,205 @@ describe('xy_expression', () => {
expect(component.find(LineSeries)).toHaveLength(1);
});
- test('it uses the full date range', () => {
- const { data, args } = sampleArgs();
+ describe('date range', () => {
+ const timeSampleLayer: LayerArgs = {
+ layerId: 'first',
+ seriesType: 'line',
+ xAccessor: 'c',
+ accessors: ['a', 'b'],
+ splitAccessor: 'd',
+ columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
+ xScaleType: 'time',
+ yScaleType: 'linear',
+ isHistogram: false,
+ };
+ const multiLayerArgs = createArgsWithLayers([
+ timeSampleLayer,
+ {
+ ...timeSampleLayer,
+ layerId: 'second',
+ seriesType: 'bar',
+ xScaleType: 'time',
+ },
+ ]);
+ test('it uses the full date range', () => {
+ const { data, args } = sampleArgs();
+
+ const component = shallow(
+
+ );
+ expect(component.find(Settings).prop('xDomain')).toMatchInlineSnapshot(`
+ Object {
+ "max": 1546491600000,
+ "min": 1546405200000,
+ "minInterval": undefined,
+ }
+ `);
+ });
- const component = shallow(
-
- );
- expect(component.find(Settings).prop('xDomain')).toMatchInlineSnapshot(`
+ test('it generates correct xDomain for a layer with single value and a layer with no data (1-0) ', () => {
+ const data: LensMultiTable = {
+ type: 'lens_multitable',
+ tables: {
+ first: createSampleDatatableWithRows([{ a: 1, b: 2, c: 'I', d: 'Foo' }]),
+ second: createSampleDatatableWithRows([]),
+ },
+ };
+
+ const component = shallow(
+
+ );
+
+ expect(component.find(Settings).prop('xDomain')).toMatchInlineSnapshot(`
+ Object {
+ "max": 1546491600000,
+ "min": 1546405200000,
+ "minInterval": 10000,
+ }
+ `);
+ });
+
+ test('it generates correct xDomain for two layers with single value(1-1)', () => {
+ const data: LensMultiTable = {
+ type: 'lens_multitable',
+ tables: {
+ first: createSampleDatatableWithRows([{ a: 1, b: 2, c: 'I', d: 'Foo' }]),
+ second: createSampleDatatableWithRows([{ a: 10, b: 5, c: 'J', d: 'Bar' }]),
+ },
+ };
+ const component = shallow(
+
+ );
+
+ expect(component.find(Settings).prop('xDomain')).toMatchInlineSnapshot(`
Object {
"max": 1546491600000,
"min": 1546405200000,
"minInterval": 10000,
}
`);
+ });
+ test('it generates correct xDomain for a layer with single value and layer with multiple value data (1-n)', () => {
+ const data: LensMultiTable = {
+ type: 'lens_multitable',
+ tables: {
+ first: createSampleDatatableWithRows([{ a: 1, b: 2, c: 'I', d: 'Foo' }]),
+ second: createSampleDatatableWithRows([
+ { a: 10, b: 5, c: 'J', d: 'Bar' },
+ { a: 8, b: 5, c: 'K', d: 'Buzz' },
+ ]),
+ },
+ };
+ const component = shallow(
+
+ );
+
+ expect(component.find(Settings).prop('xDomain')).toMatchInlineSnapshot(`
+ Object {
+ "max": 1546491600000,
+ "min": 1546405200000,
+ "minInterval": undefined,
+ }
+ `);
+ });
+
+ test('it generates correct xDomain for 2 layers with multiple value data (n-n)', () => {
+ const data: LensMultiTable = {
+ type: 'lens_multitable',
+ tables: {
+ first: createSampleDatatableWithRows([
+ { a: 1, b: 2, c: 'I', d: 'Foo' },
+ { a: 8, b: 5, c: 'K', d: 'Buzz' },
+ { a: 9, b: 7, c: 'L', d: 'Bar' },
+ { a: 10, b: 2, c: 'G', d: 'Bear' },
+ ]),
+ second: createSampleDatatableWithRows([
+ { a: 10, b: 5, c: 'J', d: 'Bar' },
+ { a: 8, b: 4, c: 'K', d: 'Fi' },
+ { a: 1, b: 8, c: 'O', d: 'Pi' },
+ ]),
+ },
+ };
+ const component = shallow(
+
+ );
+
+ expect(component.find(Settings).prop('xDomain')).toMatchInlineSnapshot(`
+ Object {
+ "max": 1546491600000,
+ "min": 1546405200000,
+ "minInterval": undefined,
+ }
+ `);
+ });
});
test('it does not use date range if the x is not a time scale', () => {
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx
index a7d4b2a217f37..f5798688badc5 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx
@@ -211,14 +211,19 @@ export function XYChart({
const shouldRotate = isHorizontalChart(layers);
const xTitle = (xAxisColumn && xAxisColumn.name) || args.xTitle;
- const interval = parseInterval(xAxisColumn?.meta?.aggConfigParams?.interval);
+
+ // add minInterval only for single row value as it cannot be determined from dataset
+
+ const minInterval = layers.every(layer => data.tables[layer.layerId].rows.length <= 1)
+ ? parseInterval(xAxisColumn?.meta?.aggConfigParams?.interval)?.asMilliseconds()
+ : undefined;
const xDomain =
data.dateRange && layers.every(l => l.xScaleType === 'time')
? {
min: data.dateRange.fromDate.getTime(),
max: data.dateRange.toDate.getTime(),
- minInterval: interval?.asMilliseconds(),
+ minInterval,
}
: undefined;
return (
From d0e7f98f97b359a652949ea80c886f0bd843d11d Mon Sep 17 00:00:00 2001
From: Marta Bondyra
Date: Thu, 2 Apr 2020 11:15:49 +0200
Subject: [PATCH 10/99] [HomeApp] Set breadcrumbs when coming back from add
data dir (#62186)
---
src/plugins/home/public/application/components/home.js | 4 ++++
src/plugins/home/public/application/components/home.test.js | 3 +++
2 files changed, 7 insertions(+)
diff --git a/src/plugins/home/public/application/components/home.js b/src/plugins/home/public/application/components/home.js
index 6d00b1c6a5d14..77cde6a574aec 100644
--- a/src/plugins/home/public/application/components/home.js
+++ b/src/plugins/home/public/application/components/home.js
@@ -36,6 +36,7 @@ import {
EuiPageBody,
EuiScreenReaderOnly,
} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
import { Welcome } from './welcome';
import { getServices } from '../kibana_services';
@@ -69,6 +70,9 @@ export class Home extends Component {
componentDidMount() {
this._isMounted = true;
this.fetchIsNewKibanaInstance();
+
+ const homeTitle = i18n.translate('home.breadcrumbs.homeTitle', { defaultMessage: 'Home' });
+ getServices().chrome.setBreadcrumbs([{ text: homeTitle }]);
}
fetchIsNewKibanaInstance = async () => {
diff --git a/src/plugins/home/public/application/components/home.test.js b/src/plugins/home/public/application/components/home.test.js
index ca8297800b53e..99722df18e069 100644
--- a/src/plugins/home/public/application/components/home.test.js
+++ b/src/plugins/home/public/application/components/home.test.js
@@ -29,6 +29,9 @@ jest.mock('../kibana_services', () => ({
getBasePath: () => 'path',
tutorialVariables: () => ({}),
homeConfig: { disableWelcomeScreen: false },
+ chrome: {
+ setBreadcrumbs: () => {},
+ },
}),
}));
From b4fd1eb6737bfe5c6b48dff4581642720ba6f109 Mon Sep 17 00:00:00 2001
From: Maryia Lapata
Date: Thu, 2 Apr 2020 12:31:10 +0300
Subject: [PATCH 11/99] [NP] Remove IndexedArray usage in Schemas (#61410)
* Remove IndexedArray usage from schemas.ts
* Update unit tests
* Revert default value
* Update sidebar.tsx
* Updated TS
* Fix code review comments
* Remove ISchemas
* Revert ISchemas
Co-authored-by: Elastic Machine
---
.../public/components/agg_group.test.tsx | 31 +++++++++++--------
.../public/components/agg_group.tsx | 4 +--
.../public/components/sidebar/sidebar.tsx | 7 ++---
.../vis_default_editor/public/schemas.ts | 30 +++++-------------
4 files changed, 30 insertions(+), 42 deletions(-)
diff --git a/src/legacy/core_plugins/vis_default_editor/public/components/agg_group.test.tsx b/src/legacy/core_plugins/vis_default_editor/public/components/agg_group.test.tsx
index 5d02f0a2c759e..483446daed10f 100644
--- a/src/legacy/core_plugins/vis_default_editor/public/components/agg_group.test.tsx
+++ b/src/legacy/core_plugins/vis_default_editor/public/components/agg_group.test.tsx
@@ -24,7 +24,7 @@ import { IAggConfigs, IAggConfig } from 'src/plugins/data/public';
import { DefaultEditorAggGroup, DefaultEditorAggGroupProps } from './agg_group';
import { DefaultEditorAgg } from './agg';
import { DefaultEditorAggAdd } from './agg_add';
-import { Schema } from '../schemas';
+import { ISchemas, Schemas } from '../schemas';
import { EditorVisState } from './sidebar/state/reducers';
jest.mock('@elastic/eui', () => ({
@@ -47,6 +47,7 @@ jest.mock('./agg_add', () => ({
describe('DefaultEditorAgg component', () => {
let defaultProps: DefaultEditorAggGroupProps;
let aggs: IAggConfigs;
+ let schemas: ISchemas;
let setTouched: jest.Mock;
let setValidity: jest.Mock;
let reorderAggs: jest.Mock;
@@ -55,6 +56,18 @@ describe('DefaultEditorAgg component', () => {
setTouched = jest.fn();
setValidity = jest.fn();
reorderAggs = jest.fn();
+ schemas = new Schemas([
+ {
+ name: 'metrics',
+ group: 'metrics',
+ max: 1,
+ },
+ {
+ name: 'buckets',
+ group: 'buckets',
+ max: 1,
+ },
+ ]);
aggs = {
aggs: [
@@ -95,18 +108,7 @@ describe('DefaultEditorAgg component', () => {
state: {
data: { aggs },
} as EditorVisState,
- schemas: [
- {
- name: 'metrics',
- group: 'metrics',
- max: 1,
- } as Schema,
- {
- name: 'buckets',
- group: 'buckets',
- max: 1,
- } as Schema,
- ],
+ schemas: schemas.metrics,
setTouched,
setValidity,
reorderAggs,
@@ -133,6 +135,7 @@ describe('DefaultEditorAgg component', () => {
it('should last bucket has truthy isLastBucket prop', () => {
defaultProps.groupName = 'buckets';
+ defaultProps.schemas = schemas.buckets;
const comp = mount();
const lastAgg = comp.find(DefaultEditorAgg).last();
@@ -154,6 +157,8 @@ describe('DefaultEditorAgg component', () => {
it('should show add button when schemas count is less than max', () => {
defaultProps.groupName = 'buckets';
+ defaultProps.schemas = schemas.buckets;
+ defaultProps.schemas[0].max = 2;
const comp = shallow();
expect(comp.find(DefaultEditorAggAdd).exists()).toBeTruthy();
diff --git a/src/legacy/core_plugins/vis_default_editor/public/components/agg_group.tsx b/src/legacy/core_plugins/vis_default_editor/public/components/agg_group.tsx
index f50abc3ebb599..792595fd421f6 100644
--- a/src/legacy/core_plugins/vis_default_editor/public/components/agg_group.tsx
+++ b/src/legacy/core_plugins/vis_default_editor/public/components/agg_group.tsx
@@ -41,7 +41,7 @@ import {
getEnabledMetricAggsCount,
} from './agg_group_helper';
import { aggGroupReducer, initAggsState, AGGS_ACTION_KEYS } from './agg_group_state';
-import { Schema, getSchemasByGroup } from '../schemas';
+import { Schema } from '../schemas';
import { TimeRange } from '../../../../../plugins/data/public';
export interface DefaultEditorAggGroupProps extends DefaultEditorAggCommonProps {
@@ -73,7 +73,7 @@ function DefaultEditorAggGroup({
}: DefaultEditorAggGroupProps) {
const groupNameLabel = (search.aggs.aggGroupNamesMap() as any)[groupName];
// e.g. buckets can have no aggs
- const schemaNames = getSchemasByGroup(schemas, groupName).map(s => s.name);
+ const schemaNames = schemas.map(s => s.name);
const group: IAggConfig[] = useMemo(
() =>
state.data.aggs!.aggs.filter(
diff --git a/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/sidebar.tsx b/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/sidebar.tsx
index 071e10682e22c..b24486a12fd24 100644
--- a/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/sidebar.tsx
+++ b/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/sidebar.tsx
@@ -31,8 +31,7 @@ import { DefaultEditorAggCommonProps } from '../agg_common_props';
import { SidebarTitle } from './sidebar_title';
import { PersistedState } from '../../../../../../plugins/visualizations/public';
import { SavedSearch } from '../../../../../../plugins/discover/public';
-import { AggGroupNames } from '../../../../../../plugins/data/public';
-import { getSchemasByGroup } from '../../schemas';
+import { Schema } from '../../schemas';
import { TimeRange } from '../../../../../../plugins/data/public';
interface DefaultEditorSideBarProps {
@@ -66,9 +65,7 @@ function DefaultEditorSideBar({
const responseAggs = useMemo(() => (state.data.aggs ? state.data.aggs.getResponseAggs() : []), [
state.data.aggs,
]);
- const metricSchemas = getSchemasByGroup(vis.type.schemas.all || [], AggGroupNames.Metrics).map(
- s => s.name
- );
+ const metricSchemas = (vis.type.schemas.metrics || []).map((s: Schema) => s.name);
const metricAggs = useMemo(
() => responseAggs.filter(agg => metricSchemas.includes(get(agg, 'schema'))),
[responseAggs, metricSchemas]
diff --git a/src/legacy/core_plugins/vis_default_editor/public/schemas.ts b/src/legacy/core_plugins/vis_default_editor/public/schemas.ts
index 94e3ad6023f4e..4e632da44afc0 100644
--- a/src/legacy/core_plugins/vis_default_editor/public/schemas.ts
+++ b/src/legacy/core_plugins/vis_default_editor/public/schemas.ts
@@ -17,11 +17,10 @@
* under the License.
*/
-import _ from 'lodash';
+import _, { defaults } from 'lodash';
import { Optional } from '@kbn/utility-types';
-import { IndexedArray } from 'ui/indexed_array';
import { AggGroupNames, AggParam, IAggGroupNames } from '../../../../plugins/data/public';
export interface ISchemas {
@@ -45,9 +44,10 @@ export interface Schema {
aggSettings?: any;
}
-export class Schemas {
- // @ts-ignore
- all: IndexedArray;
+export class Schemas implements ISchemas {
+ all: Schema[] = [];
+ [AggGroupNames.Buckets]: Schema[] = [];
+ [AggGroupNames.Metrics]: Schema[] = [];
constructor(
schemas: Array<
@@ -70,7 +70,7 @@ export class Schemas {
] as AggParam[];
}
- _.defaults(schema, {
+ defaults(schema, {
min: 0,
max: Infinity,
group: AggGroupNames.Buckets,
@@ -83,22 +83,12 @@ export class Schemas {
return schema as Schema;
})
.tap((fullSchemas: Schema[]) => {
- this.all = new IndexedArray({
- index: ['name'],
- group: ['group'],
- immutable: true,
- initialSet: fullSchemas,
- });
+ this.all = fullSchemas;
})
.groupBy('group')
.forOwn((group, groupName) => {
// @ts-ignore
- this[groupName] = new IndexedArray({
- index: ['name'],
- immutable: true,
- // @ts-ignore
- initialSet: group,
- });
+ this[groupName] = group;
})
.commit();
}
@@ -107,7 +97,3 @@ export class Schemas {
export const getSchemaByName = (schemas: Schema[], schemaName?: string) => {
return schemas.find(s => s.name === schemaName) || ({} as Schema);
};
-
-export const getSchemasByGroup = (schemas: Schema[], schemaGroup?: string) => {
- return schemas.filter(s => s.group === schemaGroup);
-};
From addb87d779818c84df25f1d727b15e601859777e Mon Sep 17 00:00:00 2001
From: Uladzislau Lasitsa
Date: Thu, 2 Apr 2020 12:53:14 +0300
Subject: [PATCH 12/99] Move `src/legacy/server/index_patterns` to data plugin
(server) (Remove step) (#61618)
* Removed legacy index pattern
* fix type
* remove unnecessary import
* Removed old references to indexPatternsServiceFactory
Co-authored-by: Elastic Machine
---
kibana.d.ts | 1 -
src/legacy/server/index_patterns/index.ts | 25 ---------
src/legacy/server/index_patterns/mixin.ts | 56 -------------------
src/legacy/server/kbn_server.d.ts | 3 -
src/legacy/server/kbn_server.js | 2 -
.../saved_objects/saved_objects_mixin.test.js | 5 --
.../lib/adapters/framework/adapter_types.ts | 3 -
.../framework/kibana_framework_adapter.ts | 5 +-
8 files changed, 1 insertion(+), 99 deletions(-)
delete mode 100644 src/legacy/server/index_patterns/index.ts
delete mode 100644 src/legacy/server/index_patterns/mixin.ts
diff --git a/kibana.d.ts b/kibana.d.ts
index 68538320e05a2..21e3e99abaa90 100644
--- a/kibana.d.ts
+++ b/kibana.d.ts
@@ -37,7 +37,6 @@ import * as LegacyKibanaServer from './src/legacy/server/kbn_server';
*/
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace Legacy {
- export type IndexPatternsService = LegacyKibanaServer.IndexPatternsService;
export type KibanaConfig = LegacyKibanaServer.KibanaConfig;
export type Request = LegacyKibanaServer.Request;
export type ResponseToolkit = LegacyKibanaServer.ResponseToolkit;
diff --git a/src/legacy/server/index_patterns/index.ts b/src/legacy/server/index_patterns/index.ts
deleted file mode 100644
index 75d0038cf9023..0000000000000
--- a/src/legacy/server/index_patterns/index.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export { indexPatternsMixin } from './mixin';
-export {
- IndexPatternsFetcher,
- FieldDescriptor,
-} from '../../../plugins/data/server/index_patterns/fetcher';
-export { IndexPatternsServiceFactory } from './mixin';
diff --git a/src/legacy/server/index_patterns/mixin.ts b/src/legacy/server/index_patterns/mixin.ts
deleted file mode 100644
index 6b04c3842007b..0000000000000
--- a/src/legacy/server/index_patterns/mixin.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { IndexPatternsFetcher } from '../../../plugins/data/server';
-import KbnServer from '../kbn_server';
-import { APICaller, CallAPIOptions } from '../../../core/server';
-import { Legacy } from '../../../../kibana';
-
-export function indexPatternsMixin(kbnServer: KbnServer, server: Legacy.Server) {
- /**
- * Create an instance of the IndexPatternsService
- *
- * @method server.indexPatternsServiceFactory
- * @type {IndexPatternsService}
- */
- server.decorate('server', 'indexPatternsServiceFactory', ({ callCluster }) => {
- return new IndexPatternsFetcher(callCluster);
- });
-
- /**
- * Get an instance of the IndexPatternsService configured for use
- * the current request
- *
- * @method request.getIndexPatternsService
- * @type {IndexPatternsService}
- */
- server.addMemoizedFactoryToRequest('getIndexPatternsService', (request: Legacy.Request) => {
- const { callWithRequest } = request.server.plugins.elasticsearch.getCluster('data');
- const callCluster: APICaller = (
- endpoint: string,
- params?: Record,
- options?: CallAPIOptions
- ) => callWithRequest(request, endpoint, params, options);
- return server.indexPatternsServiceFactory({ callCluster });
- });
-}
-
-export type IndexPatternsServiceFactory = (args: {
- callCluster: (endpoint: string, clientParams: any, options: any) => Promise;
-}) => IndexPatternsFetcher;
diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts
index d43ddf581da90..a9b8c29374854 100644
--- a/src/legacy/server/kbn_server.d.ts
+++ b/src/legacy/server/kbn_server.d.ts
@@ -44,7 +44,6 @@ import { LegacyConfig, ILegacyService, ILegacyInternals } from '../../core/serve
import { ApmOssPlugin } from '../core_plugins/apm_oss';
import { CallClusterWithRequest, ElasticsearchPlugin } from '../core_plugins/elasticsearch';
import { UsageCollectionSetup } from '../../plugins/usage_collection/server';
-import { IndexPatternsServiceFactory } from './index_patterns';
import { Capabilities } from '../../core/server';
import { UiSettingsServiceFactoryOptions } from '../../legacy/ui/ui_settings/ui_settings_service_factory';
import { HomeServerPluginSetup } from '../../plugins/home/server';
@@ -68,7 +67,6 @@ declare module 'hapi' {
interface Server {
config: () => KibanaConfig;
- indexPatternsServiceFactory: IndexPatternsServiceFactory;
savedObjects: SavedObjectsLegacyService;
injectUiAppVars: (pluginName: string, getAppVars: () => { [key: string]: any }) => void;
getHiddenUiAppById(appId: string): UiApp;
@@ -175,5 +173,4 @@ export default class KbnServer {
export { Server, Request, ResponseToolkit } from 'hapi';
// Re-export commonly accessed api types.
-export { IndexPatternsFetcher as IndexPatternsService } from './index_patterns';
export { SavedObjectsLegacyService, SavedObjectsClient } from 'src/core/server';
diff --git a/src/legacy/server/kbn_server.js b/src/legacy/server/kbn_server.js
index e06212d87e3e3..1168d24254911 100644
--- a/src/legacy/server/kbn_server.js
+++ b/src/legacy/server/kbn_server.js
@@ -33,7 +33,6 @@ import pidMixin from './pid';
import configCompleteMixin from './config/complete';
import optimizeMixin from '../../optimize';
import * as Plugins from './plugins';
-import { indexPatternsMixin } from './index_patterns';
import { savedObjectsMixin } from './saved_objects/saved_objects_mixin';
import { capabilitiesMixin } from './capabilities';
import { serverExtensionsMixin } from './server_extensions';
@@ -114,7 +113,6 @@ export default class KbnServer {
// setup this.uiBundles
uiMixin,
- indexPatternsMixin,
// setup saved object routes
savedObjectsMixin,
diff --git a/src/legacy/server/saved_objects/saved_objects_mixin.test.js b/src/legacy/server/saved_objects/saved_objects_mixin.test.js
index 3fa9f9a936988..d49b18ee2ce6c 100644
--- a/src/legacy/server/saved_objects/saved_objects_mixin.test.js
+++ b/src/legacy/server/saved_objects/saved_objects_mixin.test.js
@@ -118,11 +118,6 @@ describe('Saved Objects Mixin', () => {
get: stubConfig,
};
},
- indexPatternsServiceFactory: () => {
- return {
- getFieldsForWildcard: jest.fn(),
- };
- },
plugins: {
elasticsearch: {
getCluster: () => {
diff --git a/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts
index ca5b4cc1e4b83..8ddd3935bcc33 100644
--- a/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts
@@ -21,9 +21,6 @@ export interface InfraServerPluginDeps {
spaces: SpacesPluginSetup;
usageCollection: UsageCollectionSetup;
metrics: VisTypeTimeseriesSetup;
- indexPatterns: {
- indexPatternsServiceFactory: any;
- };
features: FeaturesPluginSetup;
apm: APMPluginContract;
alerting: AlertingPluginContract;
diff --git a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts
index e2ff93ce356e6..b73acd6703054 100644
--- a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts
@@ -7,7 +7,6 @@
/* eslint-disable @typescript-eslint/array-type */
import { GraphQLSchema } from 'graphql';
-import { Legacy } from 'kibana';
import { runHttpQuery } from 'apollo-server-core';
import { schema, TypeOf } from '@kbn/config-schema';
import {
@@ -217,9 +216,7 @@ export class KibanaFramework {
});
}
- public getIndexPatternsService(
- requestContext: RequestHandlerContext
- ): Legacy.IndexPatternsService {
+ public getIndexPatternsService(requestContext: RequestHandlerContext): IndexPatternsFetcher {
return new IndexPatternsFetcher((...rest: Parameters) => {
rest[1] = rest[1] || {};
rest[1].allowNoIndices = true;
From f7470576b7028a50e6b11de0e54d418993caab96 Mon Sep 17 00:00:00 2001
From: Walter Rafelsberger
Date: Thu, 2 Apr 2020 12:02:58 +0200
Subject: [PATCH 13/99] [ML] Clear Kibana index pattern cache on creation or
form reset. (#62184)
Clears the Kibana index pattern cache ...
- when reopening the "Create Analytics job" flyout
- after creating a transform or analyticsjob (this fixes moving from transforms to discover after creating a transform)
---
.../use_create_analytics_form/use_create_analytics_form.ts | 3 +++
.../file_based/components/import_view/import_view.js | 2 ++
.../components/step_create/step_create_form.tsx | 2 ++
3 files changed, 7 insertions(+)
diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts
index 34f1d04264900..44bfc0c5a472c 100644
--- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts
+++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts
@@ -138,6 +138,8 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => {
const id = await newIndexPattern.create();
+ await mlContext.indexPatterns.clearCache();
+
// id returns false if there's a duplicate index pattern.
if (id === false) {
addRequestMessage({
@@ -248,6 +250,7 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => {
};
const openModal = async () => {
+ await mlContext.indexPatterns.clearCache();
resetForm();
await prepareFormValidation();
dispatch({ type: ACTION.OPEN_MODAL });
diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js
index 94627b688b03a..0a58153e374df 100644
--- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js
+++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js
@@ -610,6 +610,8 @@ async function createKibanaIndexPattern(
const id = await emptyPattern.create();
+ await indexPatterns.clearCache();
+
// check if there's a default index pattern, if not,
// set the newly created one as the default index pattern.
if (!kibanaConfig.get('defaultIndex')) {
diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx
index 49be2e67ce552..5dcaece28bdde 100644
--- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx
+++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx
@@ -185,6 +185,8 @@ export const StepCreateForm: FC = React.memo(
const id = await newIndexPattern.create();
+ await indexPatterns.clearCache();
+
// id returns false if there's a duplicate index pattern.
if (id === false) {
toastNotifications.addDanger(
From a06e33ece00c071d3c54c35e467b7ac6c8161ea0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cau=C3=AA=20Marcondes?=
<55978943+cauemarcondes@users.noreply.github.com>
Date: Thu, 2 Apr 2020 11:44:46 +0100
Subject: [PATCH 14/99] changing duration type to ms, s, m (#62265)
---
.../runtime_types/duration_rt.test.ts | 2 +-
.../agent_configuration/runtime_types/duration_rt.ts | 2 +-
.../__snapshots__/index.test.ts.snap | 12 ++++++------
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/x-pack/plugins/apm/common/agent_configuration/runtime_types/duration_rt.test.ts b/x-pack/plugins/apm/common/agent_configuration/runtime_types/duration_rt.test.ts
index 6b81031542c34..a83ee9262cad6 100644
--- a/x-pack/plugins/apm/common/agent_configuration/runtime_types/duration_rt.test.ts
+++ b/x-pack/plugins/apm/common/agent_configuration/runtime_types/duration_rt.test.ts
@@ -25,7 +25,7 @@ describe('durationRt', () => {
});
describe('It should accept', () => {
- ['1s', '2m', '3h'].map(input => {
+ ['1000ms', '2s', '3m'].map(input => {
it(`${JSON.stringify(input)}`, () => {
expect(isRight(durationRt.decode(input))).toBe(true);
});
diff --git a/x-pack/plugins/apm/common/agent_configuration/runtime_types/duration_rt.ts b/x-pack/plugins/apm/common/agent_configuration/runtime_types/duration_rt.ts
index 99e6a57089dee..383fd69be9a78 100644
--- a/x-pack/plugins/apm/common/agent_configuration/runtime_types/duration_rt.ts
+++ b/x-pack/plugins/apm/common/agent_configuration/runtime_types/duration_rt.ts
@@ -8,7 +8,7 @@ import * as t from 'io-ts';
import { either } from 'fp-ts/lib/Either';
import { amountAndUnitToObject } from '../amount_and_unit';
-export const DURATION_UNITS = ['s', 'm', 'h'];
+export const DURATION_UNITS = ['ms', 's', 'm'];
export const durationRt = new t.Type(
'durationRt',
diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap
index 0c585bec22f6c..81adf76ac4ce9 100644
--- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap
+++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap
@@ -17,9 +17,9 @@ Array [
"key": "api_request_time",
"type": "duration",
"units": Array [
+ "ms",
"s",
"m",
- "h",
],
"validationError": "Please specify an integer and a unit",
"validationName": "durationRt",
@@ -82,9 +82,9 @@ Array [
"key": "profiling_inferred_spans_min_duration",
"type": "duration",
"units": Array [
+ "ms",
"s",
"m",
- "h",
],
"validationError": "Please specify an integer and a unit",
"validationName": "durationRt",
@@ -93,9 +93,9 @@ Array [
"key": "profiling_inferred_spans_sampling_interval",
"type": "duration",
"units": Array [
+ "ms",
"s",
"m",
- "h",
],
"validationError": "Please specify an integer and a unit",
"validationName": "durationRt",
@@ -109,9 +109,9 @@ Array [
"key": "server_timeout",
"type": "duration",
"units": Array [
+ "ms",
"s",
"m",
- "h",
],
"validationError": "Please specify an integer and a unit",
"validationName": "durationRt",
@@ -120,9 +120,9 @@ Array [
"key": "span_frames_min_duration",
"type": "duration",
"units": Array [
+ "ms",
"s",
"m",
- "h",
],
"validationError": "Please specify an integer and a unit",
"validationName": "durationRt",
@@ -137,9 +137,9 @@ Array [
"key": "stress_monitor_cpu_duration_threshold",
"type": "duration",
"units": Array [
+ "ms",
"s",
"m",
- "h",
],
"validationError": "Please specify an integer and a unit",
"validationName": "durationRt",
From 02dad029239c578d037ddb08ab5c5533ed94d16a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?=
Date: Thu, 2 Apr 2020 07:48:42 -0400
Subject: [PATCH 15/99] Rename some alert types (#61693)
* Rename some alert types
* Use sentence case for remaining changes + fix jest test
Co-authored-by: Elastic Machine
---
.../notifications/rules_notification_alert_type.ts | 2 +-
.../detection_engine/signals/signal_rule_alert_type.ts | 2 +-
.../lib/alert_types/__tests__/monitor_status.test.ts | 2 +-
.../uptime/public/lib/alert_types/monitor_status.tsx | 2 +-
.../alert_types/index_threshold/alert_type.test.ts | 2 +-
.../server/alert_types/index_threshold/alert_type.ts | 2 +-
x-pack/plugins/alerting_builtins/server/plugin.test.ts | 2 +-
x-pack/plugins/apm/common/alert_types.ts | 4 ++--
.../alerting/metrics/metric_threshold_alert_type.ts | 2 +-
.../register_metric_threshold_alert_type.ts | 2 +-
x-pack/plugins/triggers_actions_ui/README.md | 2 +-
.../server/lib/alerts/__tests__/status_check.test.ts | 2 +-
.../plugins/uptime/server/lib/alerts/status_check.ts | 2 +-
.../apps/triggers_actions_ui/alerts.ts | 10 +++++-----
14 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts
index 32e64138ff6e0..e74da583e9193 100644
--- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts
+++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts
@@ -20,7 +20,7 @@ export const rulesNotificationAlertType = ({
logger: Logger;
}): NotificationAlertTypeDefinition => ({
id: NOTIFICATIONS_ID,
- name: 'SIEM Notifications',
+ name: 'SIEM notification',
actionGroups: siemRuleActionGroups,
defaultActionGroupId: 'default',
validate: {
diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts
index 78b0cd84eeda3..91905722fbca3 100644
--- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts
+++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts
@@ -41,7 +41,7 @@ export const signalRulesAlertType = ({
}): SignalRuleAlertTypeDefinition => {
return {
id: SIGNALS_ID,
- name: 'SIEM Signals',
+ name: 'SIEM signal',
actionGroups: siemRuleActionGroups,
defaultActionGroupId: 'default',
validate: {
diff --git a/x-pack/legacy/plugins/uptime/public/lib/alert_types/__tests__/monitor_status.test.ts b/x-pack/legacy/plugins/uptime/public/lib/alert_types/__tests__/monitor_status.test.ts
index 34b330e9ca1b0..81402c00e484e 100644
--- a/x-pack/legacy/plugins/uptime/public/lib/alert_types/__tests__/monitor_status.test.ts
+++ b/x-pack/legacy/plugins/uptime/public/lib/alert_types/__tests__/monitor_status.test.ts
@@ -174,7 +174,7 @@ describe('monitor status alert type', () => {
{{context.downMonitorsWithGeo}}",
"iconClass": "uptimeApp",
"id": "xpack.uptime.alerts.monitorStatus",
- "name": "Uptime Monitor Status",
+ "name": "Uptime monitor status",
"validate": [Function],
}
`);
diff --git a/x-pack/legacy/plugins/uptime/public/lib/alert_types/monitor_status.tsx b/x-pack/legacy/plugins/uptime/public/lib/alert_types/monitor_status.tsx
index fde25ea30734f..d059274159c7f 100644
--- a/x-pack/legacy/plugins/uptime/public/lib/alert_types/monitor_status.tsx
+++ b/x-pack/legacy/plugins/uptime/public/lib/alert_types/monitor_status.tsx
@@ -61,7 +61,7 @@ export const initMonitorStatusAlertType: AlertTypeInitializer = ({
autocomplete,
}): AlertTypeModel => ({
id: 'xpack.uptime.alerts.monitorStatus',
- name: 'Uptime Monitor Status',
+ name: 'Uptime monitor status',
iconClass: 'uptimeApp',
alertParamsExpression: params => {
return ;
diff --git a/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.test.ts b/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.test.ts
index 5c15c398dbdcd..315e4800d4c73 100644
--- a/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.test.ts
+++ b/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.test.ts
@@ -20,7 +20,7 @@ describe('alertType', () => {
it('alert type creation structure is the expected value', async () => {
expect(alertType.id).toBe('.index-threshold');
- expect(alertType.name).toBe('Index Threshold');
+ expect(alertType.name).toBe('Index threshold');
expect(alertType.actionGroups).toEqual([{ id: 'threshold met', name: 'Threshold Met' }]);
expect(alertType.actionVariables).toMatchInlineSnapshot(`
diff --git a/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.ts b/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.ts
index 6d27f8a99dd4b..4d79efc7c9478 100644
--- a/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.ts
+++ b/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/alert_type.ts
@@ -22,7 +22,7 @@ export function getAlertType(service: Service): AlertType {
const { logger } = service;
const alertTypeName = i18n.translate('xpack.alertingBuiltins.indexThreshold.alertTypeTitle', {
- defaultMessage: 'Index Threshold',
+ defaultMessage: 'Index threshold',
});
const actionGroupName = i18n.translate(
diff --git a/x-pack/plugins/alerting_builtins/server/plugin.test.ts b/x-pack/plugins/alerting_builtins/server/plugin.test.ts
index 6bcf0379d5abe..f93041fa3c142 100644
--- a/x-pack/plugins/alerting_builtins/server/plugin.test.ts
+++ b/x-pack/plugins/alerting_builtins/server/plugin.test.ts
@@ -37,7 +37,7 @@ describe('AlertingBuiltins Plugin', () => {
},
],
"id": ".index-threshold",
- "name": "Index Threshold",
+ "name": "Index threshold",
}
`);
});
diff --git a/x-pack/plugins/apm/common/alert_types.ts b/x-pack/plugins/apm/common/alert_types.ts
index 51e1f88512965..8a342fab71e66 100644
--- a/x-pack/plugins/apm/common/alert_types.ts
+++ b/x-pack/plugins/apm/common/alert_types.ts
@@ -14,7 +14,7 @@ export enum AlertType {
export const ALERT_TYPES_CONFIG = {
[AlertType.ErrorRate]: {
name: i18n.translate('xpack.apm.errorRateAlert.name', {
- defaultMessage: 'Error rate threshold'
+ defaultMessage: 'Error rate'
}),
actionGroups: [
{
@@ -28,7 +28,7 @@ export const ALERT_TYPES_CONFIG = {
},
[AlertType.TransactionDuration]: {
name: i18n.translate('xpack.apm.transactionDurationAlert.name', {
- defaultMessage: 'Transaction duration threshold'
+ defaultMessage: 'Transaction duration'
}),
actionGroups: [
{
diff --git a/x-pack/plugins/infra/public/components/alerting/metrics/metric_threshold_alert_type.ts b/x-pack/plugins/infra/public/components/alerting/metrics/metric_threshold_alert_type.ts
index 60c4e013d79ac..04179e34222c5 100644
--- a/x-pack/plugins/infra/public/components/alerting/metrics/metric_threshold_alert_type.ts
+++ b/x-pack/plugins/infra/public/components/alerting/metrics/metric_threshold_alert_type.ts
@@ -15,7 +15,7 @@ export function getAlertType(): AlertTypeModel {
return {
id: METRIC_THRESHOLD_ALERT_TYPE_ID,
name: i18n.translate('xpack.infra.metrics.alertFlyout.alertName', {
- defaultMessage: 'Metric Threshold',
+ defaultMessage: 'Metric threshold',
}),
iconClass: 'bell',
alertParamsExpression: Expressions,
diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts
index 57f9124db923c..2ab3a3322661d 100644
--- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts
+++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts
@@ -83,7 +83,7 @@ export async function registerMetricThresholdAlertType(alertingPlugin: PluginSet
alertingPlugin.registerType({
id: METRIC_THRESHOLD_ALERT_TYPE_ID,
- name: 'Metric Alert - Threshold',
+ name: 'Metric threshold',
validate: {
params: schema.object({
criteria: schema.arrayOf(schema.oneOf([countCriterion, nonCountCriterion])),
diff --git a/x-pack/plugins/triggers_actions_ui/README.md b/x-pack/plugins/triggers_actions_ui/README.md
index 3b6ca4f9da7cc..40a43f20d44f5 100644
--- a/x-pack/plugins/triggers_actions_ui/README.md
+++ b/x-pack/plugins/triggers_actions_ui/README.md
@@ -67,7 +67,7 @@ AlertTypeModel:
export function getAlertType(): AlertTypeModel {
return {
id: '.index-threshold',
- name: 'Index Threshold',
+ name: 'Index threshold',
iconClass: 'alert',
alertParamsExpression: IndexThresholdAlertTypeExpression,
validate: validateAlertType,
diff --git a/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts b/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts
index 9c99da63c3952..08a3bc75fa8bd 100644
--- a/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts
+++ b/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts
@@ -315,7 +315,7 @@ describe('status check alert', () => {
it('contains the expected static fields like id, name, etc.', () => {
expect(alert.id).toBe('xpack.uptime.alerts.monitorStatus');
- expect(alert.name).toBe('Uptime Monitor Status');
+ expect(alert.name).toBe('Uptime monitor status');
expect(alert.defaultActionGroupId).toBe('xpack.uptime.alerts.actionGroups.monitorStatus');
expect(alert.actionGroups).toMatchInlineSnapshot(`
Array [
diff --git a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts
index 2c731687c52fc..829e6f92d3702 100644
--- a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts
+++ b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts
@@ -176,7 +176,7 @@ const DEFAULT_MAX_MESSAGE_ROWS = 3;
export const statusCheckAlertFactory: UptimeAlertTypeFactory = (server, libs) => ({
id: 'xpack.uptime.alerts.monitorStatus',
name: i18n.translate('xpack.uptime.alerts.monitorStatus', {
- defaultMessage: 'Uptime Monitor Status',
+ defaultMessage: 'Uptime monitor status',
}),
validate: {
params: schema.object({
diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts
index beedd6390388d..347eb5e14d0a8 100644
--- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts
+++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts
@@ -92,7 +92,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
{
name: alertName,
tagsText: '',
- alertType: 'Index Threshold',
+ alertType: 'Index threshold',
interval: '1m',
},
]);
@@ -154,7 +154,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
{
name: createdAlert.name,
tagsText: 'foo, bar',
- alertType: 'Index Threshold',
+ alertType: 'Index threshold',
interval: '1m',
},
]);
@@ -179,7 +179,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
{
name: updatedAlertName,
tagsText: 'foo, bar',
- alertType: 'Index Threshold',
+ alertType: 'Index threshold',
interval: '1m',
},
]);
@@ -210,7 +210,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
{
name: createdAlert.name,
tagsText: 'foo, bar',
- alertType: 'Index Threshold',
+ alertType: 'Index threshold',
interval: '1m',
},
]);
@@ -260,7 +260,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
{
name: createdAlert.name,
tagsText: 'foo, bar',
- alertType: 'Index Threshold',
+ alertType: 'Index threshold',
interval: '1m',
},
]);
From a7309a6f4eceaed471dce98021854c6002af0fcf Mon Sep 17 00:00:00 2001
From: CJ Cenizal
Date: Thu, 2 Apr 2020 05:25:48 -0700
Subject: [PATCH 16/99] Show server name in Remote Cluster detail panel
(#62250)
* Fix text size for connection status and seeds.
---
.../connection_status/connection_status.js | 2 +-
.../detail_panel/detail_panel.js | 24 ++++++++++++++++++-
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/connection_status.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/connection_status.js
index f032636af0bc3..e71320f51049f 100644
--- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/connection_status.js
+++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/connection_status.js
@@ -44,7 +44,7 @@ export function ConnectionStatus({ isConnected, mode }) {
{icon}
- {message}
+ {message}
diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.js
index 4006422d3df50..94c5fd6ce7c3f 100644
--- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.js
+++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/detail_panel/detail_panel.js
@@ -230,7 +230,9 @@ export class DetailPanel extends Component {
{seeds.map(seed => (
- {seed}
+
+ {seed}
+
))}
@@ -296,6 +298,7 @@ export class DetailPanel extends Component {
proxySocketConnections,
connectedSocketsCount,
mode,
+ serverName,
}) {
return (
@@ -398,6 +401,25 @@ export class DetailPanel extends Component {
+
+
+
+
+
+
+
+
+
+
+
+
+ {serverName ? serverName : '-'}
+
+
+
);
}
From 2df0b41959da01338d63fc91f8561f07bbe595cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?=
Date: Thu, 2 Apr 2020 14:49:59 +0200
Subject: [PATCH 17/99] [backport] Bump to 5.1.3 (#62286)
---
package.json | 2 +-
yarn.lock | 20 ++++++++++++++++----
2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index cdc41a2d8a3f0..49b5baecda474 100644
--- a/package.json
+++ b/package.json
@@ -395,7 +395,7 @@
"babel-eslint": "^10.0.3",
"babel-jest": "^24.9.0",
"babel-plugin-istanbul": "^5.2.0",
- "backport": "5.1.2",
+ "backport": "5.1.3",
"chai": "3.5.0",
"chance": "1.0.18",
"cheerio": "0.22.0",
diff --git a/yarn.lock b/yarn.lock
index a6b3154c89d05..8176eab436afd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4627,6 +4627,11 @@
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
+"@types/safe-json-stringify@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@types/safe-json-stringify/-/safe-json-stringify-1.1.0.tgz#4cd786442d7abc037f8e9026b22e3b401005c287"
+ integrity sha512-iIQqHp8fqDgxTlWor4DrTrKGVmjDeGDodQBipQkPSlRU1QeKIytv37U4aFN9N65VJcFJx67+zOnpbTNQzqHTOg==
+
"@types/seedrandom@>=2.0.0 <4.0.0":
version "2.4.28"
resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.28.tgz#9ce8fa048c1e8c85cb71d7fe4d704e000226036f"
@@ -7196,11 +7201,12 @@ backo2@1.0.2:
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
-backport@5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/backport/-/backport-5.1.2.tgz#d9be0b0f89e5140fdcc778158db00beef92481ec"
- integrity sha512-CexygdCdhUR7Br16CNUo/bfgvoa6ItKoEWJ9oPIFeIONWatYV2NA7U3uMpn74qmuJkDmrOi9SmDutxg96+qWPw==
+backport@5.1.3:
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/backport/-/backport-5.1.3.tgz#6fa788f48ee90e2b98b4e8d6d9385b0fb2e2f689"
+ integrity sha512-fTrXAyXvsg+lOuuWQosHzz/YnFfrkBsVkPcygjrDZVlWhbD+cA8mY3GrcJ8sIFwUg9Ja8qCeBFfLIRKlOwuzEg==
dependencies:
+ "@types/safe-json-stringify" "^1.1.0"
axios "^0.19.2"
dedent "^0.7.0"
del "^5.1.0"
@@ -7211,6 +7217,7 @@ backport@5.1.2:
lodash.uniq "^4.5.0"
make-dir "^3.0.2"
ora "^4.0.3"
+ safe-json-stringify "^1.2.0"
strip-json-comments "^3.0.1"
winston "^3.2.1"
yargs "^15.3.1"
@@ -26003,6 +26010,11 @@ safe-json-parse@~1.0.1:
resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57"
integrity sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=
+safe-json-stringify@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd"
+ integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==
+
safe-regex@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
From 71ff45ad6a78316de873306bebf29f6b76dbf053 Mon Sep 17 00:00:00 2001
From: Victor Martinez
Date: Thu, 2 Apr 2020 14:51:42 +0100
Subject: [PATCH 18/99] [APM] E2E: install dependencies for vanilla workspaces
(#62178)
---
x-pack/legacy/plugins/apm/e2e/package.json | 2 +
x-pack/legacy/plugins/apm/e2e/run-e2e.sh | 14 +-
x-pack/legacy/plugins/apm/e2e/yarn.lock | 144 ++++++++++++++++++++-
3 files changed, 150 insertions(+), 10 deletions(-)
diff --git a/x-pack/legacy/plugins/apm/e2e/package.json b/x-pack/legacy/plugins/apm/e2e/package.json
index 57500dfe3fdc8..150ad5bb13d0b 100644
--- a/x-pack/legacy/plugins/apm/e2e/package.json
+++ b/x-pack/legacy/plugins/apm/e2e/package.json
@@ -13,6 +13,7 @@
"@types/cypress-cucumber-preprocessor": "^1.14.1",
"@types/js-yaml": "^3.12.1",
"@types/node": "^10.12.11",
+ "axios": "^0.19.2",
"cypress": "^4.2.0",
"cypress-cucumber-preprocessor": "^2.0.1",
"js-yaml": "^3.13.1",
@@ -21,6 +22,7 @@
"p-retry": "^4.2.0",
"ts-loader": "^6.2.2",
"typescript": "3.8.3",
+ "yargs": "^15.3.1",
"wait-on": "^4.0.1",
"webpack": "^4.42.1"
}
diff --git a/x-pack/legacy/plugins/apm/e2e/run-e2e.sh b/x-pack/legacy/plugins/apm/e2e/run-e2e.sh
index 5e55dc1eb834d..7c17c14dc9601 100755
--- a/x-pack/legacy/plugins/apm/e2e/run-e2e.sh
+++ b/x-pack/legacy/plugins/apm/e2e/run-e2e.sh
@@ -75,6 +75,13 @@ if [ $? -ne 0 ]; then
exit 1
fi
+#
+# Cypress
+##################################################
+echo "\n${bold}Cypress (logs: ${TMP_DIR}/e2e-yarn.log)${normal}"
+echo "Installing cypress dependencies "
+yarn &> ${TMP_DIR}/e2e-yarn.log
+
#
# Static mock data
##################################################
@@ -99,13 +106,6 @@ if [ $? -ne 0 ]; then
exit 1
fi
-#
-# Cypress
-##################################################
-echo "\n${bold}Cypress (logs: ${TMP_DIR}/e2e-yarn.log)${normal}"
-echo "Installing cypress dependencies "
-yarn &> ${TMP_DIR}/e2e-yarn.log
-
#
# Wait for Kibana to start
##################################################
diff --git a/x-pack/legacy/plugins/apm/e2e/yarn.lock b/x-pack/legacy/plugins/apm/e2e/yarn.lock
index b7b531a9c73c0..c023c64eb1cf4 100644
--- a/x-pack/legacy/plugins/apm/e2e/yarn.lock
+++ b/x-pack/legacy/plugins/apm/e2e/yarn.lock
@@ -1288,7 +1288,7 @@ ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
-ansi-styles@^4.1.0:
+ansi-styles@^4.0.0, ansi-styles@^4.1.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359"
integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==
@@ -1429,6 +1429,13 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==
+axios@^0.19.2:
+ version "0.19.2"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
+ integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
+ dependencies:
+ follow-redirects "1.5.10"
+
babel-loader@^8.0.2:
version "8.0.6"
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb"
@@ -1845,6 +1852,11 @@ cachedir@2.3.0:
resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8"
integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==
+camelcase@^5.0.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
caniuse-lite@^1.0.30001023:
version "1.0.30001027"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001027.tgz#283e2ef17d94889cc216a22c6f85303d78ca852d"
@@ -2010,6 +2022,15 @@ cli-truncate@^0.2.1:
slice-ansi "0.0.4"
string-width "^1.0.1"
+cliui@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
+ integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.0"
+ wrap-ansi "^6.2.0"
+
clone@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
@@ -2417,7 +2438,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
dependencies:
ms "2.0.0"
-debug@3.1.0:
+debug@3.1.0, debug@=3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
@@ -2438,6 +2459,11 @@ debug@^3.0.1, debug@^3.1.0:
dependencies:
ms "^2.1.1"
+decamelize@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+ integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+
decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
@@ -2621,6 +2647,11 @@ elliptic@^6.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.0"
+emoji-regex@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+ integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
emojis-list@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
@@ -2933,6 +2964,14 @@ find-up@^3.0.0:
dependencies:
locate-path "^3.0.0"
+find-up@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
flush-write-stream@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
@@ -2951,6 +2990,13 @@ folktale@2.3.2:
resolved "https://registry.yarnpkg.com/folktale/-/folktale-2.3.2.tgz#38231b039e5ef36989920cbf805bf6b227bf4fd4"
integrity sha512-+8GbtQBwEqutP0v3uajDDoN64K2ehmHd0cjlghhxh0WpcfPzAIjPA03e1VvHlxL02FVGR0A6lwXsNQKn3H1RNQ==
+follow-redirects@1.5.10:
+ version "1.5.10"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
+ integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
+ dependencies:
+ debug "=3.1.0"
+
for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -3041,6 +3087,11 @@ get-assigned-identifiers@^1.2.0:
resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1"
integrity sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==
+get-caller-file@^2.0.1:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+ integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
get-func-name@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
@@ -3418,6 +3469,11 @@ is-fullwidth-code-point@^2.0.0:
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
+is-fullwidth-code-point@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+ integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
is-generator@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/is-generator/-/is-generator-1.0.3.tgz#c14c21057ed36e328db80347966c693f886389f3"
@@ -3779,6 +3835,13 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
lodash.clonedeep@4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
@@ -4328,7 +4391,7 @@ p-finally@^1.0.0:
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
-p-limit@^2.0.0, p-limit@^2.2.1:
+p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.1:
version "2.2.2"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e"
integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==
@@ -4342,6 +4405,13 @@ p-locate@^3.0.0:
dependencies:
p-limit "^2.0.0"
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
p-map@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
@@ -4428,6 +4498,11 @@ path-exists@^3.0.0:
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@@ -4836,11 +4911,21 @@ request@cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16:
tunnel-agent "^0.6.0"
uuid "^3.3.2"
+require-directory@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+ integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
+
require-from-string@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+require-main-filename@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
+ integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+
resolve-url@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
@@ -4982,6 +5067,11 @@ serialize-javascript@^2.1.2:
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61"
integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==
+set-blocking@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+ integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
+
set-value@^2.0.0, set-value@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
@@ -5316,6 +5406,15 @@ string-width@^2.1.1:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
+string-width@^4.1.0, string-width@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
+ integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.0"
+
string_decoder@^1.0.0, string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
@@ -5856,6 +5955,11 @@ webpack@^4.42.1:
watchpack "^1.6.0"
webpack-sources "^1.4.1"
+which-module@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
+ integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
+
which@^1.2.9:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
@@ -5878,6 +5982,15 @@ wrap-ansi@^3.0.1:
string-width "^2.1.1"
strip-ansi "^4.0.0"
+wrap-ansi@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
+ integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
@@ -5903,6 +6016,31 @@ yallist@^3.0.2:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
+yargs-parser@^18.1.1:
+ version "18.1.2"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.2.tgz#2f482bea2136dbde0861683abea7756d30b504f1"
+ integrity sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ==
+ dependencies:
+ camelcase "^5.0.0"
+ decamelize "^1.2.0"
+
+yargs@^15.3.1:
+ version "15.3.1"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b"
+ integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==
+ dependencies:
+ cliui "^6.0.0"
+ decamelize "^1.2.0"
+ find-up "^4.1.0"
+ get-caller-file "^2.0.1"
+ require-directory "^2.1.1"
+ require-main-filename "^2.0.0"
+ set-blocking "^2.0.0"
+ string-width "^4.2.0"
+ which-module "^2.0.0"
+ y18n "^4.0.0"
+ yargs-parser "^18.1.1"
+
yauzl@2.10.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
From 4a20567fb7ec89ebde0dd7f6f336ceec90475459 Mon Sep 17 00:00:00 2001
From: Andrew Cholakian
Date: Thu, 2 Apr 2020 09:06:15 -0500
Subject: [PATCH 19/99] [Uptime] Remove static constant for index name
completely (#62256)
Fixes #62255 . There were some remaining usages of a static defined
index name.
Co-authored-by: Elastic Machine
---
.../plugins/uptime/common/constants/index.ts | 1 -
.../uptime/common/constants/index_names.ts | 9 ---------
.../ml/ml_flyout_container.tsx | 19 +++++++++++++++----
.../uptime/public/state/actions/ml_anomaly.ts | 14 ++++++++++----
.../uptime/public/state/actions/types.ts | 4 ++++
.../uptime/public/state/api/ml_anomaly.ts | 14 ++++++++++----
.../server/lib/requests/get_monitor_status.ts | 5 ++---
7 files changed, 41 insertions(+), 25 deletions(-)
delete mode 100644 x-pack/legacy/plugins/uptime/common/constants/index_names.ts
diff --git a/x-pack/legacy/plugins/uptime/common/constants/index.ts b/x-pack/legacy/plugins/uptime/common/constants/index.ts
index 19f2de3c6f0f4..74783cf46550f 100644
--- a/x-pack/legacy/plugins/uptime/common/constants/index.ts
+++ b/x-pack/legacy/plugins/uptime/common/constants/index.ts
@@ -8,7 +8,6 @@ export { ACTION_GROUP_DEFINITIONS } from './alerts';
export { CHART_FORMAT_LIMITS } from './chart_format_limits';
export { CLIENT_DEFAULTS } from './client_defaults';
export { CONTEXT_DEFAULTS } from './context_defaults';
-export { INDEX_NAMES } from './index_names';
export * from './capabilities';
export { PLUGIN } from './plugin';
export { QUERY, STATES } from './query';
diff --git a/x-pack/legacy/plugins/uptime/common/constants/index_names.ts b/x-pack/legacy/plugins/uptime/common/constants/index_names.ts
deleted file mode 100644
index 9f33d280a1268..0000000000000
--- a/x-pack/legacy/plugins/uptime/common/constants/index_names.ts
+++ /dev/null
@@ -1,9 +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.
- */
-
-export const INDEX_NAMES = {
- HEARTBEAT: 'heartbeat-8*',
-};
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx
index fad12de94fd81..0a3226bc064a8 100644
--- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx
@@ -12,6 +12,7 @@ import {
hasMLJobSelector,
hasNewMLJobSelector,
isMLJobCreatingSelector,
+ selectDynamicSettings,
} from '../../../state/selectors';
import { createMLJobAction, getExistingMLJobAction } from '../../../state/actions';
import { MLJobLink } from './ml_job_link';
@@ -24,6 +25,7 @@ import { MLFlyoutView } from './ml_flyout';
import { ML_JOB_ID } from '../../../../common/constants';
import { UptimeRefreshContext, UptimeSettingsContext } from '../../../contexts';
import { useUrlParams } from '../../../hooks';
+import { getDynamicSettings } from '../../../state/actions/dynamic_settings';
interface Props {
onClose: () => void;
@@ -65,6 +67,12 @@ export const MachineLearningFlyout: React.FC = ({ onClose }) => {
const dispatch = useDispatch();
const { data: hasMLJob, error } = useSelector(hasNewMLJobSelector);
const isMLJobCreating = useSelector(isMLJobCreatingSelector);
+ const { settings } = useSelector(selectDynamicSettings);
+ useEffect(() => {
+ // Attempt to load or refresh the dynamic settings
+ dispatch(getDynamicSettings({}));
+ }, [dispatch]);
+ const heartbeatIndices = settings?.heartbeatIndices || '';
const { basePath } = useContext(UptimeSettingsContext);
const { refreshApp } = useContext(UptimeRefreshContext);
@@ -72,9 +80,12 @@ export const MachineLearningFlyout: React.FC = ({ onClose }) => {
let { monitorId } = useParams();
monitorId = atob(monitorId || '');
- const createMLJob = () => dispatch(createMLJobAction.get({ monitorId: monitorId as string }));
+ const canCreateMLJob = useSelector(canCreateMLJobSelector) && heartbeatIndices !== '';
- const canCreateMLJob = useSelector(canCreateMLJobSelector);
+ // This function is a noop in the form's disabled state
+ const createMLJob = heartbeatIndices
+ ? () => dispatch(createMLJobAction.get({ monitorId: monitorId as string, heartbeatIndices }))
+ : () => null;
const { data: uptimeJobs } = useSelector(hasMLJobSelector);
@@ -130,9 +141,9 @@ export const MachineLearningFlyout: React.FC = ({ onClose }) => {
useEffect(() => {
if (hasExistingMLJob) {
setIsCreatingJob(true);
- dispatch(createMLJobAction.get({ monitorId: monitorId as string }));
+ dispatch(createMLJobAction.get({ monitorId: monitorId as string, heartbeatIndices }));
}
- }, [dispatch, hasExistingMLJob, monitorId]);
+ }, [dispatch, hasExistingMLJob, heartbeatIndices, monitorId]);
if (hasExistingMLJob) {
return null;
diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/ml_anomaly.ts b/x-pack/legacy/plugins/uptime/public/state/actions/ml_anomaly.ts
index 9a8e4036f2cff..2e83490b71b54 100644
--- a/x-pack/legacy/plugins/uptime/public/state/actions/ml_anomaly.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/actions/ml_anomaly.ts
@@ -8,7 +8,12 @@ import { createAction } from 'redux-actions';
import { createAsyncAction } from './utils';
import { PrivilegesResponse } from '../../../../../../plugins/ml/common/types/privileges';
import { AnomaliesTableRecord } from '../../../../../../plugins/ml/common/types/anomalies';
-import { CreateMLJobSuccess, DeleteJobResults, MonitorIdParam } from './types';
+import {
+ CreateMLJobSuccess,
+ DeleteJobResults,
+ MonitorIdParam,
+ HeartbeatIndicesParam,
+} from './types';
import { JobExistResult } from '../../../../../../plugins/ml/common/types/data_recognizer';
export const resetMLState = createAction('RESET_ML_STATE');
@@ -17,9 +22,10 @@ export const getExistingMLJobAction = createAsyncAction(
- 'CREATE_ML_JOB'
-);
+export const createMLJobAction = createAsyncAction<
+ MonitorIdParam & HeartbeatIndicesParam,
+ CreateMLJobSuccess | null
+>('CREATE_ML_JOB');
export const getMLCapabilitiesAction = createAsyncAction(
'GET_ML_CAPABILITIES'
diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/types.ts b/x-pack/legacy/plugins/uptime/public/state/actions/types.ts
index 236b263414a26..41381afd31453 100644
--- a/x-pack/legacy/plugins/uptime/public/state/actions/types.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/actions/types.ts
@@ -22,6 +22,10 @@ export interface MonitorIdParam {
monitorId: string;
}
+export interface HeartbeatIndicesParam {
+ heartbeatIndices: string;
+}
+
export interface QueryParams {
monitorId: string;
dateStart: string;
diff --git a/x-pack/legacy/plugins/uptime/public/state/api/ml_anomaly.ts b/x-pack/legacy/plugins/uptime/public/state/api/ml_anomaly.ts
index 80b97783769b5..0b31a74a40133 100644
--- a/x-pack/legacy/plugins/uptime/public/state/api/ml_anomaly.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/api/ml_anomaly.ts
@@ -7,9 +7,14 @@
import moment from 'moment';
import { apiService } from './utils';
import { AnomalyRecords, AnomalyRecordsParams } from '../actions';
-import { API_URLS, INDEX_NAMES, ML_JOB_ID, ML_MODULE_ID } from '../../../common/constants';
+import { API_URLS, ML_JOB_ID, ML_MODULE_ID } from '../../../common/constants';
import { PrivilegesResponse } from '../../../../../../plugins/ml/common/types/privileges';
-import { CreateMLJobSuccess, DeleteJobResults, MonitorIdParam } from '../actions/types';
+import {
+ CreateMLJobSuccess,
+ DeleteJobResults,
+ MonitorIdParam,
+ HeartbeatIndicesParam,
+} from '../actions/types';
import { DataRecognizerConfigResponse } from '../../../../../../plugins/ml/common/types/modules';
import { JobExistResult } from '../../../../../../plugins/ml/common/types/data_recognizer';
@@ -25,7 +30,8 @@ export const getExistingJobs = async (): Promise => {
export const createMLJob = async ({
monitorId,
-}: MonitorIdParam): Promise => {
+ heartbeatIndices,
+}: MonitorIdParam & HeartbeatIndicesParam): Promise => {
const url = API_URLS.ML_SETUP_MODULE + ML_MODULE_ID;
const data = {
@@ -35,7 +41,7 @@ export const createMLJob = async ({
start: moment()
.subtract(24, 'h')
.valueOf(),
- indexPatternName: INDEX_NAMES.HEARTBEAT,
+ indexPatternName: heartbeatIndices,
query: {
bool: {
filter: [
diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts
index 2cebd532fd29b..cea8b819f403e 100644
--- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts
@@ -5,7 +5,6 @@
*/
import { UMElasticsearchQueryFn } from '../adapters';
-import { INDEX_NAMES } from '../../../../../legacy/plugins/uptime/common/constants';
export interface GetMonitorStatusParams {
filters?: string;
@@ -51,7 +50,7 @@ const getLocationClause = (locations: string[]) => ({
export const getMonitorStatus: UMElasticsearchQueryFn<
GetMonitorStatusParams,
GetMonitorStatusResult[]
-> = async ({ callES, filters, locations, numTimes, timerange: { from, to } }) => {
+> = async ({ callES, dynamicSettings, filters, locations, numTimes, timerange: { from, to } }) => {
const queryResults: Array> = [];
let afterKey: MonitorStatusKey | undefined;
@@ -60,7 +59,7 @@ export const getMonitorStatus: UMElasticsearchQueryFn<
// multiple status types for this alert, and this will become a parameter
const STATUS = 'down';
const esParams: any = {
- index: INDEX_NAMES.HEARTBEAT,
+ index: dynamicSettings.heartbeatIndices,
body: {
query: {
bool: {
From a729b3baef53d99ce7def144b0e05cfb71a59b64 Mon Sep 17 00:00:00 2001
From: Court Ewing
Date: Thu, 2 Apr 2020 10:27:57 -0400
Subject: [PATCH 20/99] Remove support for deprecated xpack.telemetry
configurations (#51142)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Remove support for deprecated xpack.telemetry configurations
In 7.5, we moved telemetry to OSS and dropped the xpack prefix for the
telemetry plugin configuration options. We deprecated the usage of the
xpack prefix so any existing usage would trigger a warning at startup.
In 8.0, we remove support for the deprecated xpack prefix configs for
telemetry.
* Move telemetry settings into its own document
* Use external reference instead of anchor
* Update docs/migration/migrate_8_0.asciidoc
Co-Authored-By: gchaps <33642766+gchaps@users.noreply.github.com>
* Update docs/migration/migrate_8_0.asciidoc
Co-Authored-By: gchaps <33642766+gchaps@users.noreply.github.com>
* Update docs/settings/telemetry-settings.asciidoc
Co-Authored-By: gchaps <33642766+gchaps@users.noreply.github.com>
* Update docs/settings/telemetry-settings.asciidoc
Co-Authored-By: gchaps <33642766+gchaps@users.noreply.github.com>
* Update docs/settings/telemetry-settings.asciidoc
Co-Authored-By: gchaps <33642766+gchaps@users.noreply.github.com>
* Update docs/settings/telemetry-settings.asciidoc
Co-Authored-By: gchaps <33642766+gchaps@users.noreply.github.com>
* Update docs/settings/telemetry-settings.asciidoc
Co-Authored-By: gchaps <33642766+gchaps@users.noreply.github.com>
* Update docs/settings/telemetry-settings.asciidoc
Co-Authored-By: gchaps <33642766+gchaps@users.noreply.github.com>
* Update docs/settings/telemetry-settings.asciidoc
Co-Authored-By: gchaps <33642766+gchaps@users.noreply.github.com>
* Update docs/settings/telemetry-settings.asciidoc
Co-Authored-By: gchaps <33642766+gchaps@users.noreply.github.com>
* Remove depecrated xpack.telemetry.* config from xpack_main/index.js
Co-authored-by: Alejandro Fernández Haro
Co-authored-by: Elastic Machine
Co-authored-by: Alejandro Fernández Haro
Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com>
---
docs/migration/migrate_8_0.asciidoc | 9 +++++
docs/settings/telemetry-settings.asciidoc | 38 +++++++++++++++++++
docs/setup/settings.asciidoc | 1 +
.../config/deprecation/core_deprecations.ts | 7 ----
x-pack/legacy/plugins/xpack_main/index.js | 5 ---
5 files changed, 48 insertions(+), 12 deletions(-)
create mode 100644 docs/settings/telemetry-settings.asciidoc
diff --git a/docs/migration/migrate_8_0.asciidoc b/docs/migration/migrate_8_0.asciidoc
index 4dc03222f057e..f3e30eb7e7d77 100644
--- a/docs/migration/migrate_8_0.asciidoc
+++ b/docs/migration/migrate_8_0.asciidoc
@@ -141,4 +141,13 @@ access level.
been deprecated with warnings that have been logged throughout 7.x. Please use Kibana UI to re-generate the
POST URL snippets if you depend on these for automated PDF reports.
+[float]
+=== Configurations starting with `xpack.telemetry` are no longer valid
+
+*Details:*
+The `xpack.` prefix has been removed for all telemetry configurations.
+
+*Impact:*
+For any configurations beginning with `xpack.telemetry`, remove the `xpack` prefix. Use {kibana-ref}/telemetry-settings-kbn.html#telemetry-general-settings[`telemetry.enabled`] instead.
+
// end::notable-breaking-changes[]
diff --git a/docs/settings/telemetry-settings.asciidoc b/docs/settings/telemetry-settings.asciidoc
new file mode 100644
index 0000000000000..ad5f53ad879f8
--- /dev/null
+++ b/docs/settings/telemetry-settings.asciidoc
@@ -0,0 +1,38 @@
+[[telemetry-settings-kbn]]
+=== Telemetry settings in Kibana
+++++
+Telemetry settings
+++++
+
+By default, Usage Collection (also known as Telemetry) is enabled. This
+helps us learn about the {kib} features that our users are most interested in, so we
+can focus our efforts on making them even better.
+
+You can control whether this data is sent from the {kib} servers, or if it should be sent
+from the user's browser, in case a firewall is blocking the connections from the server. Additionally, you can decide to completely disable this feature either in the config file or in {kib} via *Management > Kibana > Advanced Settings > Usage Data*.
+
+See our https://www.elastic.co/legal/privacy-statement[Privacy Statement] to learn more.
+
+[float]
+[[telemetry-general-settings]]
+==== General telemetry settings
+
+`telemetry.enabled`:: *Default: true*.
+Set to `true` to send cluster statistics to Elastic. Reporting your
+cluster statistics helps us improve your user experience. Your data is never
+shared with anyone. Set to `false` to disable statistics reporting from any
+browser connected to the {kib} instance.
+
+`telemetry.sendUsageFrom`:: *Default: 'browser'*.
+Set to `'server'` to report the cluster statistics from the {kib} server.
+If the server fails to connect to our endpoint at https://telemetry.elastic.co/, it assumes
+it is behind a firewall and falls back to `'browser'` to send it from users' browsers
+when they are navigating through {kib}.
+
+`telemetry.optIn`:: *Default: true*.
+Set to `true` to automatically opt into reporting cluster statistics. You can also opt out through
+*Advanced Settings* in {kib}.
+
+`telemetry.allowChangingOptInStatus`:: *Default: true*.
+Set to `true` to allow overwriting the `telemetry.optIn` setting via the {kib} UI.
+Note: When `false`, `telemetry.optIn` must be `true`. To disable telemetry and not allow users to change that parameter, use `telemetry.enabled`.
diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc
index fb58456ecc2cd..41fe8d337c03b 100644
--- a/docs/setup/settings.asciidoc
+++ b/docs/setup/settings.asciidoc
@@ -463,3 +463,4 @@ include::{docdir}/settings/reporting-settings.asciidoc[]
include::secure-settings.asciidoc[]
include::{docdir}/settings/security-settings.asciidoc[]
include::{docdir}/settings/spaces-settings.asciidoc[]
+include::{docdir}/settings/telemetry-settings.asciidoc[]
diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts
index d91e55115d0b1..f0b21adf62ff7 100644
--- a/src/core/server/config/deprecation/core_deprecations.ts
+++ b/src/core/server/config/deprecation/core_deprecations.ts
@@ -128,13 +128,6 @@ export const coreDeprecationProvider: ConfigDeprecationProvider = ({
renameFromRoot('optimize.lazyHost', 'optimize.watchHost'),
renameFromRoot('optimize.lazyPrebuild', 'optimize.watchPrebuild'),
renameFromRoot('optimize.lazyProxyTimeout', 'optimize.watchProxyTimeout'),
- renameFromRoot('xpack.xpack_main.telemetry.config', 'telemetry.config'),
- renameFromRoot('xpack.xpack_main.telemetry.url', 'telemetry.url'),
- renameFromRoot('xpack.xpack_main.telemetry.enabled', 'telemetry.enabled'),
- renameFromRoot('xpack.telemetry.enabled', 'telemetry.enabled'),
- renameFromRoot('xpack.telemetry.config', 'telemetry.config'),
- renameFromRoot('xpack.telemetry.banner', 'telemetry.banner'),
- renameFromRoot('xpack.telemetry.url', 'telemetry.url'),
// Monitoring renames
// TODO: Remove these from here once the monitoring plugin is migrated to NP
renameFromRoot('xpack.monitoring.enabled', 'monitoring.enabled'),
diff --git a/x-pack/legacy/plugins/xpack_main/index.js b/x-pack/legacy/plugins/xpack_main/index.js
index 4cf32b971b57e..6ce457ffbec05 100644
--- a/x-pack/legacy/plugins/xpack_main/index.js
+++ b/x-pack/legacy/plugins/xpack_main/index.js
@@ -23,11 +23,6 @@ export const xpackMain = kibana => {
config(Joi) {
return Joi.object({
enabled: Joi.boolean().default(true),
- telemetry: Joi.object({
- config: Joi.string().default(),
- enabled: Joi.boolean().default(),
- url: Joi.string().default(),
- }).default(), // deprecated
}).default();
},
From c8415b65194876129477ab615e1bb93849cef4ac Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Thu, 2 Apr 2020 09:06:57 -0600
Subject: [PATCH 21/99] [Maps] fix replaceLayerList to handle case where map is
not intialized (#62202)
---
.../plugins/maps/public/actions/map_actions.js | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/x-pack/legacy/plugins/maps/public/actions/map_actions.js b/x-pack/legacy/plugins/maps/public/actions/map_actions.js
index 415630d9f730b..aa55cf0808ef2 100644
--- a/x-pack/legacy/plugins/maps/public/actions/map_actions.js
+++ b/x-pack/legacy/plugins/maps/public/actions/map_actions.js
@@ -174,9 +174,16 @@ export function removeTrackedLayerStateForSelectedLayer() {
export function replaceLayerList(newLayerList) {
return (dispatch, getState) => {
- getLayerListRaw(getState()).forEach(({ id }) => {
- dispatch(removeLayerFromLayerList(id));
- });
+ const isMapReady = getMapReady(getState());
+ if (!isMapReady) {
+ dispatch({
+ type: CLEAR_WAITING_FOR_MAP_READY_LAYER_LIST,
+ });
+ } else {
+ getLayerListRaw(getState()).forEach(({ id }) => {
+ dispatch(removeLayerFromLayerList(id));
+ });
+ }
newLayerList.forEach(layerDescriptor => {
dispatch(addLayer(layerDescriptor));
From cf81ef64cbcad5e8e7e4f8d226b20ca8725e8d95 Mon Sep 17 00:00:00 2001
From: nnamdifrankie <56440728+nnamdifrankie@users.noreply.github.com>
Date: Thu, 2 Apr 2020 11:21:10 -0400
Subject: [PATCH 22/99] EMT-287: update schema with elastic agent id (#62252)
EMT-287: update schema with elastic agent id
---
.../plugins/endpoint/common/generate_data.ts | 10 ++++
x-pack/plugins/endpoint/common/types.ts | 5 ++
.../server/test_data/all_metadata_data.json | 20 ++++++++
.../api_integration/apis/endpoint/metadata.ts | 21 +++++++++
.../endpoint/metadata/api_feature/data.json | 47 ++++++++++++++++++-
.../metadata/api_feature/mappings.json | 19 +++++++-
6 files changed, 120 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/endpoint/common/generate_data.ts b/x-pack/plugins/endpoint/common/generate_data.ts
index 75351bb3bf07d..430ba1d422b96 100644
--- a/x-pack/plugins/endpoint/common/generate_data.ts
+++ b/x-pack/plugins/endpoint/common/generate_data.ts
@@ -83,6 +83,11 @@ const OTHER_EVENT_CATEGORIES: EventInfo[] = [
];
interface HostInfo {
+ elastic: {
+ agent: {
+ id: string;
+ };
+ };
agent: {
version: string;
id: string;
@@ -116,6 +121,11 @@ export class EndpointDocGenerator {
version: this.randomVersion(),
id: this.seededUUIDv4(),
},
+ elastic: {
+ agent: {
+ id: this.seededUUIDv4(),
+ },
+ },
host: {
id: this.seededUUIDv4(),
hostname: this.randomHostname(),
diff --git a/x-pack/plugins/endpoint/common/types.ts b/x-pack/plugins/endpoint/common/types.ts
index b3eb518e35ae3..565f47e7a0d6f 100644
--- a/x-pack/plugins/endpoint/common/types.ts
+++ b/x-pack/plugins/endpoint/common/types.ts
@@ -257,6 +257,11 @@ export type HostMetadata = Immutable<{
event: {
created: number;
};
+ elastic: {
+ agent: {
+ id: string;
+ };
+ };
endpoint: {
policy: {
id: string;
diff --git a/x-pack/plugins/endpoint/server/test_data/all_metadata_data.json b/x-pack/plugins/endpoint/server/test_data/all_metadata_data.json
index 3c824185ec083..3c8486aa127ea 100644
--- a/x-pack/plugins/endpoint/server/test_data/all_metadata_data.json
+++ b/x-pack/plugins/endpoint/server/test_data/all_metadata_data.json
@@ -23,6 +23,11 @@
"event" : {
"created" : "2020-01-23T21:56:55.336Z"
},
+ "elastic": {
+ "agent": {
+ "id": "56a75650-3c8a-4e4f-ac17-6dd729c650e2"
+ }
+ },
"endpoint" : {
"policy" : {
"id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
@@ -73,6 +78,11 @@
"event" : {
"created" : "2020-01-23T21:56:55.336Z"
},
+ "elastic": {
+ "agent": {
+ "id": "56a75650-3c8a-4e4f-ac17-6dd729c650e2"
+ }
+ },
"endpoint" : {
"policy" : {
"id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
@@ -115,6 +125,11 @@
"event" : {
"created" : "2020-01-23T21:56:55.336Z"
},
+ "elastic": {
+ "agent": {
+ "id": "c2d84d8f-d355-40de-8b54-5d318d4d1312"
+ }
+ },
"endpoint" : {
"policy" : {
"id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
@@ -165,6 +180,11 @@
"event" : {
"created" : "2020-01-23T21:56:55.336Z"
},
+ "elastic": {
+ "agent": {
+ "id": "c2d84d8f-d355-40de-8b54-5d318d4d1312"
+ }
+ },
"endpoint" : {
"policy" : {
"id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
diff --git a/x-pack/test/api_integration/apis/endpoint/metadata.ts b/x-pack/test/api_integration/apis/endpoint/metadata.ts
index a363f17df9faa..ad495d4505404 100644
--- a/x-pack/test/api_integration/apis/endpoint/metadata.ts
+++ b/x-pack/test/api_integration/apis/endpoint/metadata.ts
@@ -192,6 +192,27 @@ export default function({ getService }: FtrProviderContext) {
expect(body.request_page_index).to.eql(0);
});
+ it('metadata api should return the endpoint based on the elastic agent id', async () => {
+ const targetEndpointId = 'fc0ff548-feba-41b6-8367-65e8790d0eaf';
+ const targetElasticAgentId = '023fa40c-411d-4188-a941-4147bfadd095';
+ const { body } = await supertest
+ .post('/api/endpoint/metadata')
+ .set('kbn-xsrf', 'xxx')
+ .send({
+ filter: `elastic.agent.id:${targetElasticAgentId}`,
+ })
+ .expect(200);
+ expect(body.total).to.eql(1);
+ const resultHostId: string = body.hosts[0].host.id;
+ const resultElasticAgentId: string = body.hosts[0].elastic.agent.id;
+ expect(resultHostId).to.eql(targetEndpointId);
+ expect(resultElasticAgentId).to.eql(targetElasticAgentId);
+ expect(body.hosts[0].event.created).to.eql(1579881969541);
+ expect(body.hosts.length).to.eql(1);
+ expect(body.request_page_size).to.eql(10);
+ expect(body.request_page_index).to.eql(0);
+ });
+
it('metadata api should return all hosts when filter is empty string', async () => {
const { body } = await supertest
.post('/api/endpoint/metadata')
diff --git a/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/data.json b/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/data.json
index 56c58a2baa039..2046f46db9f53 100644
--- a/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/data.json
+++ b/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/data.json
@@ -10,6 +10,11 @@
"version": "6.6.1",
"name" : "Elastic Endpoint"
},
+ "elastic": {
+ "agent": {
+ "id": "11488bae-880b-4e7b-8d28-aac2aa9de816"
+ }
+ },
"endpoint": {
"policy": {
"id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
@@ -54,6 +59,11 @@
"version": "6.0.0",
"name" : "Elastic Endpoint"
},
+ "elastic": {
+ "agent": {
+ "id": "92ac1ce0-e1f7-409e-8af6-f17e97b1fc71"
+ }
+ },
"endpoint": {
"policy": {
"id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
@@ -97,6 +107,11 @@
"version": "6.8.0",
"name" : "Elastic Endpoint"
},
+ "elastic": {
+ "agent": {
+ "id": "023fa40c-411d-4188-a941-4147bfadd095"
+ }
+ },
"endpoint": {
"policy": {
"id": "00000000-0000-0000-0000-000000000000"
@@ -138,6 +153,11 @@
"version": "6.6.1",
"name" : "Elastic Endpoint"
},
+ "elastic": {
+ "agent": {
+ "id": "11488bae-880b-4e7b-8d28-aac2aa9de816"
+ }
+ },
"endpoint": {
"policy": {
"id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
@@ -182,6 +202,11 @@
"version": "6.0.0",
"name" : "Elastic Endpoint"
},
+ "elastic": {
+ "agent": {
+ "id": "92ac1ce0-e1f7-409e-8af6-f17e97b1fc71"
+ }
+ },
"endpoint": {
"policy": {
"id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
@@ -224,6 +249,11 @@
"version": "6.8.0",
"name" : "Elastic Endpoint"
},
+ "elastic": {
+ "agent": {
+ "id": "023fa40c-411d-4188-a941-4147bfadd095"
+ }
+ },
"endpoint": {
"policy": {
"id": "00000000-0000-0000-0000-000000000000"
@@ -266,6 +296,11 @@
"version": "6.6.1",
"name" : "Elastic Endpoint"
},
+ "elastic": {
+ "agent": {
+ "id": "11488bae-880b-4e7b-8d28-aac2aa9de816"
+ }
+ },
"endpoint": {
"policy": {
"id": "00000000-0000-0000-0000-000000000000"
@@ -309,6 +344,11 @@
"version": "6.0.0",
"name" : "Elastic Endpoint"
},
+ "elastic": {
+ "agent": {
+ "id": "92ac1ce0-e1f7-409e-8af6-f17e97b1fc71"
+ }
+ },
"endpoint": {
"policy": {
"id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
@@ -351,6 +391,11 @@
"version": "6.8.0",
"name" : "Elastic Endpoint"
},
+ "elastic": {
+ "agent": {
+ "id": "023fa40c-411d-4188-a941-4147bfadd095"
+ }
+ },
"endpoint": {
"policy": {
"id": "00000000-0000-0000-0000-000000000000"
@@ -379,4 +424,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/mappings.json b/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/mappings.json
index 61ddf3c4e65db..c9a6c183f0489 100644
--- a/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/mappings.json
+++ b/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/mappings.json
@@ -9,6 +9,23 @@
"@timestamp": {
"type": "long"
},
+ "elastic": {
+ "properties": {
+ "agent": {
+ "properties": {
+ "id": {
+ "fields": {
+ "keyword": {
+ "ignore_above": 256,
+ "type": "keyword"
+ }
+ },
+ "type": "text"
+ }
+ }
+ }
+ }
+ },
"agent": {
"properties": {
"id": {
@@ -153,4 +170,4 @@
}
}
}
-}
\ No newline at end of file
+}
From 61f2626d0ae8f3a15c67af08e8cfc3859e74fbb7 Mon Sep 17 00:00:00 2001
From: Joe Reuter
Date: Thu, 2 Apr 2020 18:12:22 +0200
Subject: [PATCH 23/99] Make d3 place nicely with object values (#62004)
---
.../components/controls/date_ranges.tsx | 11 ++++--
.../vis_type_vislib/public/vislib/lib/data.js | 36 +++++++++++++++++--
.../apps/visualize/_vertical_bar_chart.js | 19 ++++++++++
.../page_objects/visualize_editor_page.ts | 9 +++++
4 files changed, 70 insertions(+), 5 deletions(-)
diff --git a/src/legacy/core_plugins/vis_default_editor/public/components/controls/date_ranges.tsx b/src/legacy/core_plugins/vis_default_editor/public/components/controls/date_ranges.tsx
index ca4a9315d6bfb..15e864bfd026d 100644
--- a/src/legacy/core_plugins/vis_default_editor/public/components/controls/date_ranges.tsx
+++ b/src/legacy/core_plugins/vis_default_editor/public/components/controls/date_ranges.tsx
@@ -125,7 +125,7 @@ function DateRangesParamEditor({
- {ranges.map(({ from, to, id }) => {
+ {ranges.map(({ from, to, id }, index) => {
const deleteBtnTitle = i18n.translate(
'visDefaultEditor.controls.dateRanges.removeRangeButtonAriaLabel',
{
@@ -154,6 +154,7 @@ function DateRangesParamEditor({
placeholder={FROM_PLACEHOLDER}
value={from || ''}
onChange={ev => onChangeRange(id, 'from', ev.target.value)}
+ data-test-subj={`visEditorDateRange${index}__from`}
/>
@@ -168,6 +169,7 @@ function DateRangesParamEditor({
description: 'End of a date range, e.g. From 2018-02-26 *To* 2018-02-28',
}
)}
+ data-test-subj={`visEditorDateRange${index}__to`}
compressed
fullWidth={true}
isInvalid={areBothEmpty || !validateDateMath(to)}
@@ -203,7 +205,12 @@ function DateRangesParamEditor({
-
+
{
const newData = {};
Object.keys(data).forEach(key => {
- if (key !== 'series') {
- newData[key] = data[key];
- } else {
+ if (key === 'xAxisOrderedValues') {
+ newData[key] = data[key].map(val => {
+ if (typeof val === 'object') {
+ return new D3MappableObject(val);
+ }
+ return val;
+ });
+ } else if (key === 'series') {
newData[key] = data[key].map(seri => {
const converter = getFormatService().deserialize(seri.format);
const zConverter = getFormatService().deserialize(seri.zFormat);
@@ -67,12 +92,17 @@ export class Data {
const newVal = _.clone(val);
newVal.extraMetrics = val.extraMetrics;
newVal.series = val.series || seri.label;
+ if (typeof newVal.x === 'object') {
+ newVal.x = new D3MappableObject(newVal.x);
+ }
return newVal;
}),
yAxisFormatter: val => converter.convert(val),
zAxisFormatter: val => zConverter.convert(val),
};
});
+ } else {
+ newData[key] = data[key];
}
});
diff --git a/test/functional/apps/visualize/_vertical_bar_chart.js b/test/functional/apps/visualize/_vertical_bar_chart.js
index 9bb220a11a86a..d5f4c45f8bdbc 100644
--- a/test/functional/apps/visualize/_vertical_bar_chart.js
+++ b/test/functional/apps/visualize/_vertical_bar_chart.js
@@ -54,6 +54,25 @@ export default function({ getService, getPageObjects }) {
});
});
+ describe('bar charts range on x axis', () => {
+ it('should individual bars for each configured range', async function() {
+ await PageObjects.visualize.navigateToNewVisualization();
+ await PageObjects.visualize.clickVerticalBarChart();
+ await PageObjects.visualize.clickNewSearch();
+ await PageObjects.timePicker.setDefaultAbsoluteRange();
+ await PageObjects.visEditor.clickBucket('X-axis');
+ log.debug('Aggregation = Date Range');
+ await PageObjects.visEditor.selectAggregation('Date Range');
+ log.debug('Field = @timestamp');
+ await PageObjects.visEditor.selectField('@timestamp');
+ await PageObjects.visEditor.clickAddDateRange();
+ await PageObjects.visEditor.setDateRangeByIndex('1', 'now-2w/w', 'now-1w/w');
+ await PageObjects.visEditor.clickGo();
+ const bottomLabels = await PageObjects.visChart.getXAxisLabels();
+ expect(bottomLabels.length).to.be(2);
+ });
+ });
+
// FLAKY: https://github.com/elastic/kibana/issues/22322
describe.skip('vertical bar chart flaky part', function() {
const vizName1 = 'Visualization VerticalBarChart';
diff --git a/test/functional/page_objects/visualize_editor_page.ts b/test/functional/page_objects/visualize_editor_page.ts
index b1c3e924b3c1b..41c12170cf4dc 100644
--- a/test/functional/page_objects/visualize_editor_page.ts
+++ b/test/functional/page_objects/visualize_editor_page.ts
@@ -103,6 +103,15 @@ export function VisualizeEditorPageProvider({ getService, getPageObjects }: FtrP
await radioBtn.click();
}
+ public async clickAddDateRange() {
+ await testSubjects.click(`visEditorAddDateRange`);
+ }
+
+ public async setDateRangeByIndex(index: string, from: string, to: string) {
+ await testSubjects.setValue(`visEditorDateRange${index}__from`, from);
+ await testSubjects.setValue(`visEditorDateRange${index}__to`, to);
+ }
+
/**
* Adds new bucket
* @param bucketName bucket name, like 'X-axis', 'Split rows', 'Split series'
From 9a6c17d3da83d95af6a0cae9f6cee9a20118cc03 Mon Sep 17 00:00:00 2001
From: Shahzad
Date: Thu, 2 Apr 2020 19:00:34 +0200
Subject: [PATCH 24/99] =?UTF-8?q?[Uptime]=20Convert=20anomaly=20Jobs=20nam?=
=?UTF-8?q?e=20to=20lowercase=20to=20comply=20with=E2=80=A6=20(#62293)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* converted ml job name to lower case
* update type
---
.../__snapshots__/ml_job_link.test.tsx.snap | 2 +-
.../ml/ml_flyout_container.tsx | 8 +++---
.../uptime/public/state/api/ml_anomaly.ts | 25 +++++++++++++------
3 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap
index 85988af04a939..9957f13fc1334 100644
--- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap
@@ -3,7 +3,7 @@
exports[`ML JobLink renders without errors 1`] = `
diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx
index 0a3226bc064a8..9eed24e2810d8 100644
--- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx
+++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx
@@ -50,13 +50,13 @@ const showMLJobNotification = (
),
- toastLifeTimeMs: 5000,
+ toastLifeTimeMs: 10000,
});
} else {
- notifications.toasts.warning({
+ notifications.toasts.danger({
title: {labels.JOB_CREATION_FAILED}
,
body: message ?? {labels.JOB_CREATION_FAILED_MESSAGE}
,
- toastLifeTimeMs: 5000,
+ toastLifeTimeMs: 10000,
});
}
};
@@ -119,7 +119,7 @@ export const MachineLearningFlyout: React.FC = ({ onClose }) => {
basePath,
{ to: dateRangeEnd, from: dateRangeStart },
false,
- error?.body?.message
+ error?.message || error?.body?.message
);
}
setIsCreatingJob(false);
diff --git a/x-pack/legacy/plugins/uptime/public/state/api/ml_anomaly.ts b/x-pack/legacy/plugins/uptime/public/state/api/ml_anomaly.ts
index 0b31a74a40133..bcd2582fe18b9 100644
--- a/x-pack/legacy/plugins/uptime/public/state/api/ml_anomaly.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/api/ml_anomaly.ts
@@ -18,7 +18,7 @@ import {
import { DataRecognizerConfigResponse } from '../../../../../../plugins/ml/common/types/modules';
import { JobExistResult } from '../../../../../../plugins/ml/common/types/data_recognizer';
-export const getMLJobId = (monitorId: string) => `${monitorId}_${ML_JOB_ID}`;
+export const getMLJobId = (monitorId: string) => `${monitorId}_${ML_JOB_ID}`.toLowerCase();
export const getMLCapabilities = async (): Promise => {
return await apiService.get(API_URLS.ML_CAPABILITIES);
@@ -34,8 +34,11 @@ export const createMLJob = async ({
}: MonitorIdParam & HeartbeatIndicesParam): Promise => {
const url = API_URLS.ML_SETUP_MODULE + ML_MODULE_ID;
+ // ML App doesn't support upper case characters in job name
+ const lowerCaseMonitorId = monitorId.toLowerCase();
+
const data = {
- prefix: `${monitorId}_`,
+ prefix: `${lowerCaseMonitorId}_`,
useDedicatedIndex: false,
startDatafeed: true,
start: moment()
@@ -47,7 +50,7 @@ export const createMLJob = async ({
filter: [
{
term: {
- 'monitor.id': monitorId,
+ 'monitor.id': lowerCaseMonitorId,
},
},
],
@@ -56,11 +59,17 @@ export const createMLJob = async ({
};
const response: DataRecognizerConfigResponse = await apiService.post(url, data);
- if (response?.jobs?.[0]?.id === getMLJobId(monitorId) && response?.jobs?.[0]?.success) {
- return {
- count: 1,
- jobId: response?.jobs?.[0]?.id,
- };
+ if (response?.jobs?.[0]?.id === getMLJobId(monitorId)) {
+ const jobResponse = response.jobs[0];
+ if (jobResponse.success) {
+ return {
+ count: 1,
+ jobId: jobResponse.id,
+ };
+ } else {
+ const { error } = jobResponse;
+ throw new Error(error?.msg);
+ }
} else {
return null;
}
From e202fe7aa31721a4c319aa414cc4e6739b9bf000 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Thu, 2 Apr 2020 11:04:06 -0600
Subject: [PATCH 25/99] [Maps] remove MapBounds type (#62332)
---
.../maps/public/connected_components/map/mb/view.js | 8 ++++----
x-pack/legacy/plugins/maps/public/layers/layer.d.ts | 4 +++-
x-pack/legacy/plugins/maps/public/layers/layer.js | 10 +++++-----
.../plugins/maps/public/layers/sources/es_source.js | 8 ++++----
.../maps/public/layers/sources/vector_source.d.ts | 8 +++++++-
.../legacy/plugins/maps/public/layers/vector_layer.js | 8 ++++----
.../maps/common/descriptor_types/map_descriptor.ts | 10 +---------
7 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js
index fdc8ad2176d08..2995ea039e7a8 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js
+++ b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js
@@ -235,12 +235,12 @@ export class MBMapContainer extends React.Component {
//clamping ot -89/89 latitudes since Mapboxgl does not seem to handle bounds that contain the poles (logs errors to the console when using -90/90)
const lnLatBounds = new mapboxgl.LngLatBounds(
new mapboxgl.LngLat(
- clampToLonBounds(goto.bounds.min_lon),
- clampToLatBounds(goto.bounds.min_lat)
+ clampToLonBounds(goto.bounds.minLon),
+ clampToLatBounds(goto.bounds.minLat)
),
new mapboxgl.LngLat(
- clampToLonBounds(goto.bounds.max_lon),
- clampToLatBounds(goto.bounds.max_lat)
+ clampToLonBounds(goto.bounds.maxLon),
+ clampToLatBounds(goto.bounds.maxLat)
)
);
//maxZoom ensure we're not zooming in too far on single points or small shapes
diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/layer.d.ts
index 777566298e607..de59642ede8ab 100644
--- a/x-pack/legacy/plugins/maps/public/layers/layer.d.ts
+++ b/x-pack/legacy/plugins/maps/public/layers/layer.d.ts
@@ -3,12 +3,13 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import { LayerDescriptor } from '../../common/descriptor_types';
+import { LayerDescriptor, MapExtent, MapFilters } from '../../common/descriptor_types';
import { ISource } from './sources/source';
import { DataRequest } from './util/data_request';
import { SyncContext } from '../actions/map_actions';
export interface ILayer {
+ getBounds(mapFilters: MapFilters): Promise;
getDataRequest(id: string): DataRequest | undefined;
getDisplayName(source?: ISource): Promise;
getId(): string;
@@ -25,6 +26,7 @@ export interface ILayerArguments {
export class AbstractLayer implements ILayer {
constructor(layerArguments: ILayerArguments);
+ getBounds(mapFilters: MapFilters): Promise;
getDataRequest(id: string): DataRequest | undefined;
getDisplayName(source?: ISource): Promise;
getId(): string;
diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js
index d162e342dfd1a..e9616be89b601 100644
--- a/x-pack/legacy/plugins/maps/public/layers/layer.js
+++ b/x-pack/legacy/plugins/maps/public/layers/layer.js
@@ -320,12 +320,12 @@ export class AbstractLayer {
return sourceDataRequest && sourceDataRequest.hasData();
}
- async getBounds() {
+ async getBounds(/* mapFilters: MapFilters */) {
return {
- min_lon: -180,
- max_lon: 180,
- min_lat: -89,
- max_lat: 89,
+ minLon: -180,
+ maxLon: 180,
+ minLat: -89,
+ maxLat: 89,
};
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
index bf04a73cfba77..441d52d23398a 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
@@ -175,10 +175,10 @@ export class AbstractESSource extends AbstractVectorSource {
}
return {
- min_lon: esBounds.top_left.lon,
- max_lon: esBounds.bottom_right.lon,
- min_lat: esBounds.bottom_right.lat,
- max_lat: esBounds.top_left.lat,
+ minLon: esBounds.top_left.lon,
+ maxLon: esBounds.bottom_right.lon,
+ minLat: esBounds.bottom_right.lat,
+ maxLat: esBounds.top_left.lat,
};
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts
index 7a747da244233..1400654297e01 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts
@@ -8,7 +8,11 @@
import { FeatureCollection } from 'geojson';
import { AbstractSource, ISource } from './source';
import { IField } from '../fields/field';
-import { ESSearchSourceResponseMeta } from '../../../common/descriptor_types';
+import {
+ ESSearchSourceResponseMeta,
+ MapExtent,
+ VectorSourceRequestMeta,
+} from '../../../common/descriptor_types';
export type GeoJsonFetchMeta = ESSearchSourceResponseMeta;
@@ -18,6 +22,7 @@ export type GeoJsonWithMeta = {
};
export interface IVectorSource extends ISource {
+ getBoundsForFilters(searchFilters: VectorSourceRequestMeta): MapExtent;
getGeoJsonWithMeta(
layerName: 'string',
searchFilters: unknown[],
@@ -29,6 +34,7 @@ export interface IVectorSource extends ISource {
}
export class AbstractVectorSource extends AbstractSource implements IVectorSource {
+ getBoundsForFilters(searchFilters: VectorSourceRequestMeta): MapExtent;
getGeoJsonWithMeta(
layerName: 'string',
searchFilters: unknown[],
diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js
index 6b89554546330..d606420909281 100644
--- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js
+++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js
@@ -167,10 +167,10 @@ export class VectorLayer extends AbstractLayer {
features: visibleFeatures,
});
return {
- min_lon: bbox[0],
- min_lat: bbox[1],
- max_lon: bbox[2],
- max_lat: bbox[3],
+ minLon: bbox[0],
+ minLat: bbox[1],
+ maxLon: bbox[2],
+ maxLat: bbox[3],
};
}
diff --git a/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts b/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts
index b2a4c6b85a856..798b5f335dda2 100644
--- a/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts
+++ b/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts
@@ -33,16 +33,8 @@ export type MapCenterAndZoom = MapCenter & {
zoom: number;
};
-// TODO replace with map_descriptors.MapExtent. Both define the same thing but with different casing
-type MapBounds = {
- min_lon: number;
- max_lon: number;
- min_lat: number;
- max_lat: number;
-};
-
export type Goto = {
- bounds?: MapBounds;
+ bounds?: MapExtent;
center?: MapCenterAndZoom;
};
From d6587d7f5b121e6f7a982dc6847be9d62841324f Mon Sep 17 00:00:00 2001
From: Kaarina Tungseth
Date: Thu, 2 Apr 2020 13:03:50 -0500
Subject: [PATCH 26/99] Updates dashboard images (#62011)
---
.../Dashboard_add_new_visualization.png | Bin 344294 -> 427826 bytes
docs/images/Dashboard_add_visualization.png | Bin 203682 -> 430019 bytes
2 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/docs/images/Dashboard_add_new_visualization.png b/docs/images/Dashboard_add_new_visualization.png
index b871131805ab538788fd945dfdfc263126623fe2..445f1f5dd8df5b101fc6a23daa474d445668c5bd 100644
GIT binary patch
literal 427826
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