+
+
+ {}}
+ editorDidMount={setEditorCalculatedHeight}
+ aria-label={codeEditorAriaLabel}
+ options={{
+ automaticLayout: true,
+ fontSize: 12,
+ minimap: {
+ enabled: false,
+ },
+ overviewRulerBorder: false,
+ readOnly: true,
+ scrollbar: {
+ alwaysConsumeMouseWheel: false,
+ },
+ scrollBeyondLastLine: false,
+ wordWrap: 'on',
+ wrappingIndent: 'indent',
+ }}
+ />
+
+
+ );
+};
diff --git a/src/plugins/discover/public/plugin.ts b/src/plugins/discover/public/plugin.ts
index c53dfaff24112..47161c2b8298e 100644
--- a/src/plugins/discover/public/plugin.ts
+++ b/src/plugins/discover/public/plugin.ts
@@ -36,7 +36,7 @@ import { UrlGeneratorState } from '../../share/public';
import { DocViewInput, DocViewInputFn } from './application/doc_views/doc_views_types';
import { DocViewsRegistry } from './application/doc_views/doc_views_registry';
import { DocViewTable } from './application/components/table/table';
-import { JsonCodeBlock } from './application/components/json_code_block/json_code_block';
+import { JsonCodeEditor } from './application/components/json_code_editor/json_code_editor';
import {
setDocViewsRegistry,
setUrlTracker,
@@ -187,7 +187,7 @@ export class DiscoverPlugin
defaultMessage: 'JSON',
}),
order: 20,
- component: JsonCodeBlock,
+ component: JsonCodeEditor,
});
const {
diff --git a/x-pack/plugins/alerts/README.md b/x-pack/plugins/alerts/README.md
index 2191b23eec11e..aab848d4555d2 100644
--- a/x-pack/plugins/alerts/README.md
+++ b/x-pack/plugins/alerts/README.md
@@ -20,26 +20,13 @@ Table of Contents
- [Example](#example)
- [Role Based Access-Control](#role-based-access-control)
- [Alert Navigation](#alert-navigation)
- - [RESTful API](#restful-api)
- - [`POST /api/alerts/alert`: Create alert](#post-apialert-create-alert)
- - [`DELETE /api/alerts/alert/{id}`: Delete alert](#delete-apialertid-delete-alert)
- - [`GET /api/alerts/_find`: Find alerts](#get-apialertfind-find-alerts)
- - [`GET /api/alerts/alert/{id}`: Get alert](#get-apialertid-get-alert)
+ - [Experimental RESTful API](#restful-api)
- [`GET /api/alerts/alert/{id}/state`: Get alert state](#get-apialertidstate-get-alert-state)
- [`GET /api/alerts/alert/{id}/_instance_summary`: Get alert instance summary](#get-apialertidstate-get-alert-instance-summary)
- - [`GET /api/alerts/list_alert_types`: List alert types](#get-apialerttypes-list-alert-types)
- - [`PUT /api/alerts/alert/{id}`: Update alert](#put-apialertid-update-alert)
- - [`POST /api/alerts/alert/{id}/_enable`: Enable an alert](#post-apialertidenable-enable-an-alert)
- - [`POST /api/alerts/alert/{id}/_disable`: Disable an alert](#post-apialertiddisable-disable-an-alert)
- - [`POST /api/alerts/alert/{id}/_mute_all`: Mute all alert instances](#post-apialertidmuteall-mute-all-alert-instances)
- - [`POST /api/alerts/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute`: Mute alert instance](#post-apialertalertidalertinstancealertinstanceidmute-mute-alert-instance)
- - [`POST /api/alerts/alert/{id}/_unmute_all`: Unmute all alert instances](#post-apialertidunmuteall-unmute-all-alert-instances)
- - [`POST /api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute`: Unmute an alert instance](#post-apialertalertidalertinstancealertinstanceidunmute-unmute-an-alert-instance)
- [`POST /api/alerts/alert/{id}/_update_api_key`: Update alert API key](#post-apialertidupdateapikey-update-alert-api-key)
- - [Schedule Formats](#schedule-formats)
- [Alert instance factory](#alert-instance-factory)
- [Templating actions](#templating-actions)
- - [Examples](#examples)
+ - [Examples](#examples)
## Terminology
@@ -61,7 +48,7 @@ A Kibana alert detects a condition and executes one or more actions when that co
1. Develop and register an alert type (see alert types -> example).
2. Configure feature level privileges using RBAC
-3. Create an alert using the RESTful API (see alerts -> create).
+3. Create an alert using the RESTful API [Documentation](https://www.elastic.co/guide/en/kibana/master/alerts-api-update.html) (see alerts -> create).
## Limitations
@@ -96,6 +83,7 @@ The following table describes the properties of the `options` object.
|validate.params|When developing an alert type, you can choose to accept a series of parameters. You may also have the parameters validated before they are passed to the `executor` function or created as an alert saved object. In order to do this, provide a `@kbn/config-schema` schema that we will use to validate the `params` attribute.|@kbn/config-schema|
|executor|This is where the code of the alert type lives. This is a function to be called when executing an alert on an interval basis. For full details, see executor section below.|Function|
|producer|The id of the application producing this alert type.|string|
+|minimumLicenseRequired|The value of a minimum license. Most of the alerts are licensed as "basic".|string|
### Executor
@@ -142,13 +130,13 @@ This example receives server and threshold as parameters. It will read the CPU u
```typescript
import { schema } from '@kbn/config-schema';
+import { AlertType, AlertExecutorOptions } from '../../../alerts/server';
import {
- Alert,
- AlertTypeParams,
- AlertTypeState,
- AlertInstanceState,
- AlertInstanceContext
-} from 'x-pack/plugins/alerts/common';
+ AlertTypeParams,
+ AlertTypeState,
+ AlertInstanceState,
+ AlertInstanceContext,
+} from '../../../alerts/common';
...
interface MyAlertTypeParams extends AlertTypeParams {
server: string;
@@ -156,7 +144,7 @@ interface MyAlertTypeParams extends AlertTypeParams {
}
interface MyAlertTypeState extends AlertTypeState {
- lastChecked: number;
+ lastChecked: Date;
}
interface MyAlertTypeInstanceState extends AlertInstanceState {
@@ -257,83 +245,6 @@ const myAlertType: AlertType<
server.newPlatform.setup.plugins.alerts.registerType(myAlertType);
```
-This example only receives threshold as a parameter. It will read the CPU usage of all the servers and schedule individual actions if the reading for a server is greater than the threshold. This is a better implementation than above as only one query is performed for all the servers instead of one query per server.
-
-```typescript
-server.newPlatform.setup.plugins.alerts.registerType({
- id: 'my-alert-type',
- name: 'My alert type',
- validate: {
- params: schema.object({
- threshold: schema.number({ min: 0, max: 1 }),
- }),
- },
- actionGroups: [
- {
- id: 'default',
- name: 'Default',
- },
- ],
- defaultActionGroupId: 'default',
- minimumLicenseRequired: 'basic',
- actionVariables: {
- context: [
- { name: 'server', description: 'the server' },
- { name: 'hasCpuUsageIncreased', description: 'boolean indicating if the cpu usage has increased' },
- ],
- state: [
- { name: 'cpuUsage', description: 'CPU usage' },
- ],
- },
- async executor({
- alertId,
- startedAt,
- previousStartedAt,
- services,
- params,
- state,
- }: AlertExecutorOptions) {
- const { threshold } = params; // Let's assume params is { threshold: 0.8 }
-
- // Call a function to get the CPU readings on all the servers. The result will be
- // an array of { server, cpuUsage }.
- const cpuUsageByServer = await getCpuUsageByServer();
-
- for (const { server, cpuUsage: currentCpuUsage } of cpuUsageByServer) {
- // Only execute if CPU usage is greater than threshold
- if (currentCpuUsage > threshold) {
- // The first argument is a unique identifier the alert instance is about. In this scenario
- // the provided server will be used. Also, this id will be used to make `getState()` return
- // previous state, if any, on matching identifiers.
- const alertInstance = services.alertInstanceFactory(server);
-
- // State from last execution. This will exist if an alert instance was created and executed
- // in the previous execution
- const { cpuUsage: previousCpuUsage } = alertInstance.getState();
-
- // Replace state entirely with new values
- alertInstance.replaceState({
- cpuUsage: currentCpuUsage,
- });
-
- // 'default' refers to the id of a group of actions to be scheduled for execution, see 'actions' in create alert section
- alertInstance.scheduleActions('default', {
- server,
- hasCpuUsageIncreased: currentCpuUsage > previousCpuUsage,
- });
- }
- }
-
- // Single object containing state that isn't specific to a server, this will become available
- // within the `state` function parameter at the next execution
- return {
- lastChecked: new Date(),
- };
- },
- producer: 'alerting',
-});
-```
-
## Role Based Access-Control
Once you have registered your AlertType, you need to grant your users privileges to use it.
When registering a feature in Kibana you can specify multiple types of privileges which are granted to users when they're assigned certain roles.
@@ -387,29 +298,37 @@ It's important to note that any role can be granted a mix of `all` and `read` pr
```typescript
features.registerKibanaFeature({
- id: 'my-application-id',
- name: 'My Application',
- app: [],
- privileges: {
- all: {
- alerting: {
- all: [
- 'my-application-id.my-alert-type',
- 'my-application-id.my-restricted-alert-type'
- ],
- },
- },
- read: {
- alerting: {
- all: [
- 'my-application-id.my-alert-type'
- ]
- read: [
- 'my-application-id.my-restricted-alert-type'
- ],
- },
- },
- },
+ id: 'my-application-id',
+ name: 'My Application',
+ app: [],
+ privileges: {
+ all: {
+ app: ['my-application-id', 'kibana'],
+ savedObject: {
+ all: [],
+ read: [],
+ },
+ ui: [],
+ api: [],
+ },
+ read: {
+ app: ['lens', 'kibana'],
+ alerting: {
+ all: [
+ 'my-application-id.my-alert-type'
+ ],
+ read: [
+ 'my-application-id.my-restricted-alert-type'
+ ],
+ },
+ savedObject: {
+ all: [],
+ read: [],
+ },
+ ui: [],
+ api: [],
+ },
+ },
});
```
@@ -494,46 +413,10 @@ The only case in which this handler will not be used to evaluate the navigation
You can use the `registerNavigation` api to specify as many AlertType specific handlers as you like, but you can only use it once per AlertType as we wouldn't know which handler to use if you specified two for the same AlertType. For the same reason, you can only use `registerDefaultNavigation` once per plugin, as it covers all cases for your specific plugin.
-## RESTful API
-
-Using an alert type requires you to create an alert that will contain parameters and actions for a given alert type. See below for CRUD operations using the API.
+## Experimental RESTful API
-### `POST /api/alerts/alert`: Create alert
-
-Payload:
-
-|Property|Description|Type|
-|---|---|---|
-|enabled|Indicate if you want the alert to start executing on an interval basis after it has been created.|boolean|
-|name|A name to reference and search in the future.|string|
-|tags|A list of keywords to reference and search in the future.|string[]|
-|alertTypeId|The id value of the alert type you want to call when the alert is scheduled to execute.|string|
-|schedule|The schedule specifying when this alert should be run, using one of the available schedule formats specified under _Schedule Formats_ below|object|
-|throttle|A Duration specifying how often this alert should fire the same actions. This will prevent the alert from sending out the same notification over and over. For example, if an alert with a `schedule` of 1 minute stays in a triggered state for 90 minutes, setting a `throttle` of `10m` or `1h` will prevent it from sending 90 notifications over this period.|string|
-|params|The parameters to pass in to the alert type executor `params` value. This will also validate against the alert type params validator if defined.|object|
-|actions|Array of the following: - `group` (string): We support grouping actions in the scenario of escalations or different types of alert instances. If you don't need this, feel free to use `default` as a value. - `id` (string): The id of the action saved object to execute. - `params` (object): The map to the `params` the action type will receive. In order to help apply context to strings, we handle them as mustache templates and pass in a default set of context. (see templating actions).|array|
-
-### `DELETE /api/alerts/alert/{id}`: Delete alert
-
-Params:
-
-|Property|Description|Type|
-|---|---|---|
-|id|The id of the alert you're trying to delete.|string|
-
-### `GET /api/alerts/_find`: Find alerts
-
-Params:
-
-See the saved objects API documentation for find. All the properties are the same except you cannot pass in `type`.
-
-### `GET /api/alerts/alert/{id}`: Get alert
-
-Params:
-
-|Property|Description|Type|
-|---|---|---|
-|id|The id of the alert you're trying to get.|string|
+Using of the alert type requires you to create an alert that will contain parameters and actions for a given alert type. API description for CRUD operations is a part of the [user documentation](https://www.elastic.co/guide/en/kibana/master/alerts-api-update.html).
+API listed below is experimental and could be changed or removed in the future.
### `GET /api/alerts/alert/{id}/state`: Get alert state
@@ -560,93 +443,12 @@ Query:
|---|---|---|
|dateStart|The date to start looking for alert events in the event log. Either an ISO date string, or a duration string indicating time since now.|string|
-### `GET /api/alerts/list_alert_types`: List alert types
-
-No parameters.
-
-### `PUT /api/alerts/alert/{id}`: Update alert
-
-Params:
-
-|Property|Description|Type|
-|---|---|---|
-|id|The id of the alert you're trying to update.|string|
-
-Payload:
-
-|Property|Description|Type|
-|---|---|---|
-|schedule|The schedule specifying when this alert should be run, using one of the available schedule formats specified under _Schedule Formats_ below|object|
-|throttle|A Duration specifying how often this alert should fire the same actions. This will prevent the alert from sending out the same notification over and over. For example, if an alert with a `schedule` of 1 minute stays in a triggered state for 90 minutes, setting a `throttle` of `10m` or `1h` will prevent it from sending 90 notifications over this period.|string|
-|name|A name to reference and search in the future.|string|
-|tags|A list of keywords to reference and search in the future.|string[]|
-|params|The parameters to pass in to the alert type executor `params` value. This will also validate against the alert type params validator if defined.|object|
-|actions|Array of the following: - `group` (string): We support grouping actions in the scenario of escalations or different types of alert instances. If you don't need this, feel free to use `default` as a value. - `id` (string): The id of the action saved object to execute. - `params` (object): There map to the `params` the action type will receive. In order to help apply context to strings, we handle them as mustache templates and pass in a default set of context. (see templating actions).|array|
-
-### `POST /api/alerts/alert/{id}/_enable`: Enable an alert
-
-Params:
-
-|Property|Description|Type|
-|---|---|---|
-|id|The id of the alert you're trying to enable.|string|
-
-### `POST /api/alerts/alert/{id}/_disable`: Disable an alert
-
-Params:
-
-|Property|Description|Type|
-|---|---|---|
-|id|The id of the alert you're trying to disable.|string|
-
-### `POST /api/alerts/alert/{id}/_mute_all`: Mute all alert instances
-
-Params:
-
-|Property|Description|Type|
-|---|---|---|
-|id|The id of the alert you're trying to mute all alert instances for.|string|
-
-### `POST /api/alerts/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute`: Mute alert instance
-
-Params:
-
-|Property|Description|Type|
-|---|---|---|
-|alertId|The id of the alert you're trying to mute an instance for.|string|
-|alertInstanceId|The instance id of the alert instance you're trying to mute.|string|
-
-### `POST /api/alerts/alert/{id}/_unmute_all`: Unmute all alert instances
-
-Params:
-
-|Property|Description|Type|
-|---|---|---|
-|id|The id of the alert you're trying to unmute all alert instances for.|string|
-
-### `POST /api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute`: Unmute an alert instance
-
-Params:
-
-|Property|Description|Type|
-|---|---|---|
-|alertId|The id of the alert you're trying to unmute an instance for.|string|
-|alertInstanceId|The instance id of the alert instance you're trying to unmute.|string|
-
### `POST /api/alerts/alert/{id}/_update_api_key`: Update alert API key
|Property|Description|Type|
|---|---|---|
|id|The id of the alert you're trying to update the API key for. System will use user in request context to generate an API key for.|string|
-## Schedule Formats
-A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule.
-
-We currently support the _Interval format_ which specifies the interval in seconds, minutes, hours or days at which the alert should execute.
-Example: `{ interval: "10s" }`, `{ interval: "5m" }`, `{ interval: "1h" }`, `{ interval: "1d" }`.
-
-There are plans to support multiple other schedule formats in the near future.
-
## Alert instance factory
**alertInstanceFactory(id)**
@@ -694,7 +496,7 @@ When an alert instance executes, the first argument is the `group` of actions to
The templating engine is [mustache]. General definition for the [mustache variable] is a double-brace {{}}. All variables are HTML-escaped by default and if there is a requirement to render unescaped HTML, it should be applied the triple mustache: `{{{name}}}`. Also, can be used `&` to unescape a variable.
-## Examples
+### Examples
The following code would be within an alert type. As you can see `cpuUsage ` will replace the state of the alert instance and `server` is the context for the alert instance to execute. The difference between the two is `cpuUsage ` will be accessible at the next execution.
diff --git a/x-pack/plugins/maps/public/actions/map_actions.test.js b/x-pack/plugins/maps/public/actions/map_actions.test.js
index c0ad934c232e2..fafafa6b6a071 100644
--- a/x-pack/plugins/maps/public/actions/map_actions.test.js
+++ b/x-pack/plugins/maps/public/actions/map_actions.test.js
@@ -277,6 +277,9 @@ describe('map_actions', () => {
require('../selectors/map_selectors').getSearchSessionId = () => {
return searchSessionId;
};
+ require('../selectors/map_selectors').getSearchSessionMapBuffer = () => {
+ return undefined;
+ };
require('../selectors/map_selectors').getMapSettings = () => {
return {
autoFitToDataBounds: false,
diff --git a/x-pack/plugins/maps/public/actions/map_actions.ts b/x-pack/plugins/maps/public/actions/map_actions.ts
index 33c79c793974b..9682306852ba9 100644
--- a/x-pack/plugins/maps/public/actions/map_actions.ts
+++ b/x-pack/plugins/maps/public/actions/map_actions.ts
@@ -22,6 +22,7 @@ import {
getTimeFilters,
getLayerList,
getSearchSessionId,
+ getSearchSessionMapBuffer,
} from '../selectors/map_selectors';
import {
CLEAR_GOTO,
@@ -229,12 +230,14 @@ export function setQuery({
filters = [],
forceRefresh = false,
searchSessionId,
+ searchSessionMapBuffer,
}: {
filters?: Filter[];
query?: Query;
timeFilters?: TimeRange;
forceRefresh?: boolean;
searchSessionId?: string;
+ searchSessionMapBuffer?: MapExtent;
}) {
return async (
dispatch: ThunkDispatch,
@@ -255,6 +258,7 @@ export function setQuery({
},
filters: filters ? filters : getFilters(getState()),
searchSessionId,
+ searchSessionMapBuffer,
};
const prevQueryContext = {
@@ -262,6 +266,7 @@ export function setQuery({
query: getQuery(getState()),
filters: getFilters(getState()),
searchSessionId: getSearchSessionId(getState()),
+ searchSessionMapBuffer: getSearchSessionMapBuffer(getState()),
};
if (_.isEqual(nextQueryContext, prevQueryContext)) {
diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx
index a89b9879ec6c8..655308ae63246 100644
--- a/x-pack/plugins/maps/public/classes/layers/layer.tsx
+++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx
@@ -77,7 +77,7 @@ export interface ILayer {
canShowTooltip(): boolean;
syncLayerWithMB(mbMap: MbMap): void;
getLayerTypeIconName(): string;
- isDataLoaded(): boolean;
+ isInitialDataLoadComplete(): boolean;
getIndexPatternIds(): string[];
getQueryableIndexPatternIds(): string[];
getType(): string | undefined;
@@ -450,7 +450,7 @@ export class AbstractLayer implements ILayer {
throw new Error('should implement Layer#getLayerTypeIconName');
}
- isDataLoaded(): boolean {
+ isInitialDataLoadComplete(): boolean {
const sourceDataRequest = this.getSourceDataRequest();
return sourceDataRequest ? sourceDataRequest.hasData() : false;
}
diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx
index 7e87d99fd4f93..2373ed3ba2062 100644
--- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx
+++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx
@@ -174,7 +174,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer {
return this.getValidJoins().length > 0;
}
- isDataLoaded() {
+ isInitialDataLoadComplete() {
const sourceDataRequest = this.getSourceDataRequest();
if (!sourceDataRequest || !sourceDataRequest.hasData()) {
return false;
diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx
index f42a055b24d0a..b7e50815fd1f7 100644
--- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx
+++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx
@@ -44,6 +44,7 @@ import {
} from '../reducers/non_serializable_instances';
import {
getMapCenter,
+ getMapBuffer,
getMapZoom,
getHiddenLayerIds,
getQueryableUniqueIndexPatternIds,
@@ -151,11 +152,7 @@ export class MapEmbeddable
store.dispatch(disableScrollZoom());
this._dispatchSetQuery({
- query: this.input.query,
- timeRange: this.input.timeRange,
- filters: this.input.filters,
forceRefresh: false,
- searchSessionId: this.input.searchSessionId,
});
if (this.input.refreshConfig) {
this._dispatchSetRefreshConfig(this.input.refreshConfig);
@@ -230,11 +227,7 @@ export class MapEmbeddable
this.input.searchSessionId !== this._prevSearchSessionId
) {
this._dispatchSetQuery({
- query: this.input.query,
- timeRange: this.input.timeRange,
- filters: this.input.filters,
forceRefresh: false,
- searchSessionId: this.input.searchSessionId,
});
}
@@ -258,30 +251,24 @@ export class MapEmbeddable
}
}
- _dispatchSetQuery({
- query,
- timeRange,
- filters = [],
- forceRefresh,
- searchSessionId,
- }: {
- query?: Query;
- timeRange?: TimeRange;
- filters?: Filter[];
- forceRefresh: boolean;
- searchSessionId?: string;
- }) {
- this._prevTimeRange = timeRange;
- this._prevQuery = query;
- this._prevFilters = filters;
- this._prevSearchSessionId = searchSessionId;
+ _dispatchSetQuery({ forceRefresh }: { forceRefresh: boolean }) {
+ this._prevTimeRange = this.input.timeRange;
+ this._prevQuery = this.input.query;
+ this._prevFilters = this.input.filters;
+ this._prevSearchSessionId = this.input.searchSessionId;
+ const enabledFilters = this.input.filters
+ ? this.input.filters.filter((filter) => !filter.meta.disabled)
+ : [];
this._savedMap.getStore().dispatch(
setQuery({
- filters: filters.filter((filter) => !filter.meta.disabled),
- query,
- timeFilters: timeRange,
+ filters: enabledFilters,
+ query: this.input.query,
+ timeFilters: this.input.timeRange,
forceRefresh,
- searchSessionId,
+ searchSessionId: this.input.searchSessionId,
+ searchSessionMapBuffer: getIsRestore(this.input.searchSessionId)
+ ? this.input.mapBuffer
+ : undefined,
})
);
}
@@ -432,11 +419,7 @@ export class MapEmbeddable
reload() {
this._dispatchSetQuery({
- query: this.input.query,
- timeRange: this.input.timeRange,
- filters: this.input.filters,
forceRefresh: true,
- searchSessionId: this.input.searchSessionId,
});
}
@@ -457,6 +440,7 @@ export class MapEmbeddable
lon: center.lon,
zoom,
},
+ mapBuffer: getMapBuffer(this._savedMap.getStore().getState()),
});
}
diff --git a/x-pack/plugins/maps/public/embeddable/types.ts b/x-pack/plugins/maps/public/embeddable/types.ts
index 67489802bc31d..7cd4fa8e1253b 100644
--- a/x-pack/plugins/maps/public/embeddable/types.ts
+++ b/x-pack/plugins/maps/public/embeddable/types.ts
@@ -12,7 +12,7 @@ import {
SavedObjectEmbeddableInput,
} from '../../../../../src/plugins/embeddable/public';
import { RefreshInterval, Query, Filter, TimeRange } from '../../../../../src/plugins/data/common';
-import { MapCenterAndZoom } from '../../common/descriptor_types';
+import { MapCenterAndZoom, MapExtent } from '../../common/descriptor_types';
import { MapSavedObjectAttributes } from '../../common/map_saved_object_type';
import { MapSettings } from '../reducers/map';
@@ -25,6 +25,7 @@ interface MapEmbeddableState {
isLayerTOCOpen?: boolean;
openTOCDetails?: string[];
mapCenter?: MapCenterAndZoom;
+ mapBuffer?: MapExtent;
mapSettings?: Partial;
hiddenLayers?: string[];
hideFilterActions?: boolean;
diff --git a/x-pack/plugins/maps/public/reducers/map.d.ts b/x-pack/plugins/maps/public/reducers/map.d.ts
index 6a51d4feeb9df..1cf3756160964 100644
--- a/x-pack/plugins/maps/public/reducers/map.d.ts
+++ b/x-pack/plugins/maps/public/reducers/map.d.ts
@@ -37,6 +37,7 @@ export type MapContext = {
refreshTimerLastTriggeredAt?: string;
drawState?: DrawState;
searchSessionId?: string;
+ searchSessionMapBuffer?: MapExtent;
};
export type MapSettings = {
diff --git a/x-pack/plugins/maps/public/reducers/map.js b/x-pack/plugins/maps/public/reducers/map.js
index fa7e1308bac4f..9bf0df612bac4 100644
--- a/x-pack/plugins/maps/public/reducers/map.js
+++ b/x-pack/plugins/maps/public/reducers/map.js
@@ -241,7 +241,7 @@ export function map(state = DEFAULT_MAP_STATE, action) {
};
return { ...state, mapState: { ...state.mapState, ...newMapState } };
case SET_QUERY:
- const { query, timeFilters, filters, searchSessionId } = action;
+ const { query, timeFilters, filters, searchSessionId, searchSessionMapBuffer } = action;
return {
...state,
mapState: {
@@ -250,6 +250,7 @@ export function map(state = DEFAULT_MAP_STATE, action) {
timeFilters,
filters,
searchSessionId,
+ searchSessionMapBuffer,
},
};
case SET_REFRESH_CONFIG:
diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.test.ts b/x-pack/plugins/maps/public/selectors/map_selectors.test.ts
index 89cd80f4daab5..58268b6ea9d82 100644
--- a/x-pack/plugins/maps/public/selectors/map_selectors.test.ts
+++ b/x-pack/plugins/maps/public/selectors/map_selectors.test.ts
@@ -26,9 +26,67 @@ jest.mock('../kibana_services', () => ({
}));
import { DEFAULT_MAP_STORE_STATE } from '../reducers/store';
-import { areLayersLoaded, getTimeFilters } from './map_selectors';
+import { areLayersLoaded, getDataFilters, getTimeFilters } from './map_selectors';
import { LayerDescriptor } from '../../common/descriptor_types';
import { ILayer } from '../classes/layers/layer';
+import { Filter } from '../../../../../src/plugins/data/public';
+
+describe('getDataFilters', () => {
+ const mapExtent = {
+ maxLat: 1,
+ maxLon: 1,
+ minLat: 0,
+ minLon: 0,
+ };
+ const mapBuffer = {
+ maxLat: 1.5,
+ maxLon: 1.5,
+ minLat: -0.5,
+ minLon: -0.5,
+ };
+ const mapZoom = 4;
+ const timeFilters = { to: '2001-01-01', from: '2001-12-31' };
+ const refreshTimerLastTriggeredAt = '2001-01-01T00:00:00';
+ const query = undefined;
+ const filters: Filter[] = [];
+ const searchSessionId = '12345';
+ const searchSessionMapBuffer = {
+ maxLat: 1.25,
+ maxLon: 1.25,
+ minLat: -0.25,
+ minLon: -0.25,
+ };
+
+ test('should set buffer as searchSessionMapBuffer when using searchSessionId', () => {
+ const dataFilters = getDataFilters.resultFunc(
+ mapExtent,
+ mapBuffer,
+ mapZoom,
+ timeFilters,
+ refreshTimerLastTriggeredAt,
+ query,
+ filters,
+ searchSessionId,
+ searchSessionMapBuffer
+ );
+ expect(dataFilters.buffer).toEqual(searchSessionMapBuffer);
+ });
+
+ test('should fall back to screen buffer when using searchSessionId and searchSessionMapBuffer is not provided', () => {
+ const dataFilters = getDataFilters.resultFunc(
+ mapExtent,
+ mapBuffer,
+ mapZoom,
+ timeFilters,
+ refreshTimerLastTriggeredAt,
+ query,
+ filters,
+ searchSessionId,
+ undefined
+ );
+ expect(dataFilters.buffer).toEqual(mapBuffer);
+ });
+});
describe('getTimeFilters', () => {
test('should return timeFilters when contained in state', () => {
@@ -66,12 +124,12 @@ describe('getTimeFilters', () => {
describe('areLayersLoaded', () => {
function createLayerMock({
hasErrors = false,
- isDataLoaded = false,
+ isInitialDataLoadComplete = false,
isVisible = true,
showAtZoomLevel = true,
}: {
hasErrors?: boolean;
- isDataLoaded?: boolean;
+ isInitialDataLoadComplete?: boolean;
isVisible?: boolean;
showAtZoomLevel?: boolean;
}) {
@@ -79,8 +137,8 @@ describe('areLayersLoaded', () => {
hasErrors: () => {
return hasErrors;
},
- isDataLoaded: () => {
- return isDataLoaded;
+ isInitialDataLoadComplete: () => {
+ return isInitialDataLoadComplete;
},
isVisible: () => {
return isVisible;
@@ -99,35 +157,37 @@ describe('areLayersLoaded', () => {
});
test('layer should not be counted as loaded if it has not loaded', () => {
- const layerList = [createLayerMock({ isDataLoaded: false })];
+ const layerList = [createLayerMock({ isInitialDataLoadComplete: false })];
const waitingForMapReadyLayerList: LayerDescriptor[] = [];
const zoom = 4;
expect(areLayersLoaded.resultFunc(layerList, waitingForMapReadyLayerList, zoom)).toBe(false);
});
test('layer should be counted as loaded if its not visible', () => {
- const layerList = [createLayerMock({ isVisible: false, isDataLoaded: false })];
+ const layerList = [createLayerMock({ isVisible: false, isInitialDataLoadComplete: false })];
const waitingForMapReadyLayerList: LayerDescriptor[] = [];
const zoom = 4;
expect(areLayersLoaded.resultFunc(layerList, waitingForMapReadyLayerList, zoom)).toBe(true);
});
test('layer should be counted as loaded if its not shown at zoom level', () => {
- const layerList = [createLayerMock({ showAtZoomLevel: false, isDataLoaded: false })];
+ const layerList = [
+ createLayerMock({ showAtZoomLevel: false, isInitialDataLoadComplete: false }),
+ ];
const waitingForMapReadyLayerList: LayerDescriptor[] = [];
const zoom = 4;
expect(areLayersLoaded.resultFunc(layerList, waitingForMapReadyLayerList, zoom)).toBe(true);
});
test('layer should be counted as loaded if it has a loading error', () => {
- const layerList = [createLayerMock({ hasErrors: true, isDataLoaded: false })];
+ const layerList = [createLayerMock({ hasErrors: true, isInitialDataLoadComplete: false })];
const waitingForMapReadyLayerList: LayerDescriptor[] = [];
const zoom = 4;
expect(areLayersLoaded.resultFunc(layerList, waitingForMapReadyLayerList, zoom)).toBe(true);
});
test('layer should be counted as loaded if its loaded', () => {
- const layerList = [createLayerMock({ isDataLoaded: true })];
+ const layerList = [createLayerMock({ isInitialDataLoadComplete: true })];
const waitingForMapReadyLayerList: LayerDescriptor[] = [];
const zoom = 4;
expect(areLayersLoaded.resultFunc(layerList, waitingForMapReadyLayerList, zoom)).toBe(true);
diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.ts b/x-pack/plugins/maps/public/selectors/map_selectors.ts
index b16ac704c3715..35c73a2bd2f1c 100644
--- a/x-pack/plugins/maps/public/selectors/map_selectors.ts
+++ b/x-pack/plugins/maps/public/selectors/map_selectors.ts
@@ -183,6 +183,9 @@ export const getFilters = ({ map }: MapStoreState): Filter[] => map.mapState.fil
export const getSearchSessionId = ({ map }: MapStoreState): string | undefined =>
map.mapState.searchSessionId;
+export const getSearchSessionMapBuffer = ({ map }: MapStoreState): MapExtent | undefined =>
+ map.mapState.searchSessionMapBuffer;
+
export const isUsingSearch = (state: MapStoreState): boolean => {
const filters = getFilters(state).filter((filter) => !filter.meta.disabled);
const queryString = _.get(getQuery(state), 'query', '');
@@ -235,6 +238,7 @@ export const getDataFilters = createSelector(
getQuery,
getFilters,
getSearchSessionId,
+ getSearchSessionMapBuffer,
(
mapExtent,
mapBuffer,
@@ -243,11 +247,12 @@ export const getDataFilters = createSelector(
refreshTimerLastTriggeredAt,
query,
filters,
- searchSessionId
+ searchSessionId,
+ searchSessionMapBuffer
) => {
return {
extent: mapExtent,
- buffer: mapBuffer,
+ buffer: searchSessionId && searchSessionMapBuffer ? searchSessionMapBuffer : mapBuffer,
zoom: mapZoom,
timeFilters,
refreshTimerLastTriggeredAt,
@@ -432,7 +437,7 @@ export const areLayersLoaded = createSelector(
layer.isVisible() &&
layer.showAtZoomLevel(zoom) &&
!layer.hasErrors() &&
- !layer.isDataLoaded()
+ !layer.isInitialDataLoadComplete()
) {
return false;
}
diff --git a/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts b/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts
index b38cabf33a3db..3bfe2a7410c08 100644
--- a/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts
+++ b/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts
@@ -76,6 +76,6 @@ export const validateEntities = {
/**
* Indices to search in.
*/
- indices: schema.arrayOf(schema.string()),
+ indices: schema.oneOf([schema.arrayOf(schema.string()), schema.string()]),
}),
};
diff --git a/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/translations.ts b/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/translations.ts
index 3e18c7a01c808..1a007cd7f0f56 100644
--- a/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/translations.ts
+++ b/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/translations.ts
@@ -17,13 +17,13 @@ export const ENDPOINT_POLICY = i18n.translate(
export const POLICY_STATUS = i18n.translate(
'xpack.securitySolution.host.details.endpoint.policyStatus',
{
- defaultMessage: 'Configuration Status',
+ defaultMessage: 'Policy Status',
}
);
export const SENSORVERSION = i18n.translate(
'xpack.securitySolution.host.details.endpoint.sensorversion',
{
- defaultMessage: 'Sensorversion',
+ defaultMessage: 'Sensor Version',
}
);
diff --git a/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx
index 9c9c56461609d..a8cfea1de8e74 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx
@@ -30,8 +30,7 @@ import { TimelineId } from '../../../../common/types/timeline';
import { timelineSelectors } from '../../store/timeline';
import { timelineDefaults } from '../../store/timeline/defaults';
import { isFullScreen } from '../timeline/body/column_headers';
-import { useSourcererScope } from '../../../common/containers/sourcerer';
-import { SourcererScopeName } from '../../../common/store/sourcerer/model';
+import { sourcererSelectors } from '../../../common/store';
import { updateTimelineGraphEventId } from '../../../timelines/store/timeline/actions';
import { Resolver } from '../../../resolver/view';
import {
@@ -169,14 +168,12 @@ const GraphOverlayComponent: React.FC = ({ isEventViewer, timelineId }
globalFullScreen,
]);
- let sourcereScope = SourcererScopeName.default;
- if ([TimelineId.detectionsRulesDetailsPage, TimelineId.detectionsPage].includes(timelineId)) {
- sourcereScope = SourcererScopeName.detections;
- } else if (timelineId === TimelineId.active) {
- sourcereScope = SourcererScopeName.timeline;
- }
+ const existingIndexNamesSelector = useMemo(
+ () => sourcererSelectors.getAllExistingIndexNamesSelector(),
+ []
+ );
+ const existingIndexNames = useDeepEqualSelector(existingIndexNamesSelector);
- const { selectedPatterns } = useSourcererScope(sourcereScope);
return (
= ({ isEventViewer, timelineId }
diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx
index 4e101e29bb484..8fce9a186bbd4 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx
@@ -6,6 +6,7 @@
*/
import React from 'react';
+import styled from 'styled-components';
import { i18n } from '@kbn/i18n';
import { EuiTitle } from '@elastic/eui';
import { HostDetailsLink } from '../../../../common/components/links';
@@ -23,14 +24,20 @@ interface ExpandableHostProps {
hostName: string;
}
+const StyledTitle = styled.h4`
+ word-break: break-all;
+ word-wrap: break-word;
+ white-space: pre-wrap;
+`;
+
export const ExpandableHostDetailsTitle = ({ hostName }: ExpandableHostProps) => (
-