diff --git a/.sass-lint.yml b/.sass-lint.yml
index d6eaaf391de1a..9eed50602f520 100644
--- a/.sass-lint.yml
+++ b/.sass-lint.yml
@@ -1,6 +1,7 @@
files:
include:
- 'src/legacy/core_plugins/metrics/**/*.s+(a|c)ss'
+ - 'src/plugins/index_pattern_management/**/*.s+(a|c)ss'
- 'src/plugins/timelion/**/*.s+(a|c)ss'
- 'src/plugins/vis_type_vislib/**/*.s+(a|c)ss'
- 'src/plugins/vis_type_vega/**/*.s+(a|c)ss'
diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
index a03b1b74fc1ac..842f90b7047c8 100644
--- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
+++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
@@ -81,6 +81,7 @@ readonly links: {
readonly loadingData: string;
readonly introduction: string;
};
+ readonly addData: string;
readonly kibana: string;
readonly siem: {
readonly guide: string;
diff --git a/docs/setup/connect-to-elasticsearch.asciidoc b/docs/setup/connect-to-elasticsearch.asciidoc
index bffb3f97cd1b9..f750784c47043 100644
--- a/docs/setup/connect-to-elasticsearch.asciidoc
+++ b/docs/setup/connect-to-elasticsearch.asciidoc
@@ -97,7 +97,7 @@ Using a wildcard is the more popular approach.
comparisons.
+
Kibana reads the index mapping and lists all fields that contain a timestamp. If your
-index doesn't have time-based data, choose *I don't want to use the Time Filter*.
+index doesn't have time-based data, choose *I don't want to use the time filter*.
+
You must select a time field to use global time filters on your dashboards.
diff --git a/examples/embeddable_examples/kibana.json b/examples/embeddable_examples/kibana.json
index 771c19cfdbd3d..0ac40ae1889de 100644
--- a/examples/embeddable_examples/kibana.json
+++ b/examples/embeddable_examples/kibana.json
@@ -4,7 +4,7 @@
"kibanaVersion": "kibana",
"server": true,
"ui": true,
- "requiredPlugins": ["embeddable", "uiActions"],
+ "requiredPlugins": ["embeddable", "uiActions", "dashboard"],
"optionalPlugins": [],
"extraPublicDirs": ["public/todo", "public/hello_world", "public/todo/todo_ref_embeddable"],
"requiredBundles": ["kibanaReact"]
diff --git a/examples/embeddable_examples/public/book/add_book_to_library_action.tsx b/examples/embeddable_examples/public/book/add_book_to_library_action.tsx
new file mode 100644
index 0000000000000..b74a1d5642982
--- /dev/null
+++ b/examples/embeddable_examples/public/book/add_book_to_library_action.tsx
@@ -0,0 +1,55 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+import { createAction, IncompatibleActionError } from '../../../../src/plugins/ui_actions/public';
+import { BookEmbeddable, BOOK_EMBEDDABLE } from './book_embeddable';
+import { ViewMode, isReferenceOrValueEmbeddable } from '../../../../src/plugins/embeddable/public';
+
+interface ActionContext {
+ embeddable: BookEmbeddable;
+}
+
+export const ACTION_ADD_BOOK_TO_LIBRARY = 'ACTION_ADD_BOOK_TO_LIBRARY';
+
+export const createAddBookToLibraryAction = () =>
+ createAction({
+ getDisplayName: () =>
+ i18n.translate('embeddableExamples.book.addToLibrary', {
+ defaultMessage: 'Add Book To Library',
+ }),
+ type: ACTION_ADD_BOOK_TO_LIBRARY,
+ order: 100,
+ getIconType: () => 'folderCheck',
+ isCompatible: async ({ embeddable }: ActionContext) => {
+ return (
+ embeddable.type === BOOK_EMBEDDABLE &&
+ embeddable.getInput().viewMode === ViewMode.EDIT &&
+ isReferenceOrValueEmbeddable(embeddable) &&
+ !embeddable.inputIsRefType(embeddable.getInput())
+ );
+ },
+ execute: async ({ embeddable }: ActionContext) => {
+ if (!isReferenceOrValueEmbeddable(embeddable)) {
+ throw new IncompatibleActionError();
+ }
+ const newInput = await embeddable.getInputAsRefType();
+ embeddable.updateInput(newInput);
+ },
+ });
diff --git a/examples/embeddable_examples/public/book/book_component.tsx b/examples/embeddable_examples/public/book/book_component.tsx
index 064e13c131a0a..e46487641b913 100644
--- a/examples/embeddable_examples/public/book/book_component.tsx
+++ b/examples/embeddable_examples/public/book/book_component.tsx
@@ -20,7 +20,7 @@ import React from 'react';
import { EuiFlexItem, EuiFlexGroup, EuiIcon } from '@elastic/eui';
import { EuiText } from '@elastic/eui';
-import { EuiFlexGrid } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
import { withEmbeddableSubscription } from '../../../../src/plugins/embeddable/public';
import { BookEmbeddableInput, BookEmbeddableOutput, BookEmbeddable } from './book_embeddable';
@@ -44,26 +44,32 @@ function wrapSearchTerms(task?: string, search?: string) {
);
}
-export function BookEmbeddableComponentInner({ input: { search }, output: { attributes } }: Props) {
+export function BookEmbeddableComponentInner({
+ input: { search },
+ output: { attributes },
+ embeddable,
+}: Props) {
const title = attributes?.title;
const author = attributes?.author;
const readIt = attributes?.readIt;
+ const byReference = embeddable.inputIsRefType(embeddable.getInput());
+
return (
-
-
-
- {mappingConflictLabel}
+ {mappingConflictLabel}
+
+
+ {wrapSearchTerms(title, search)},
+ {wrapSearchTerms(title, search)}
-{wrapSearchTerms(author, search)}
+ -{wrapSearchTerms(author, search)}
-
-
-
-
@@ -127,6 +127,7 @@ export const Header: React.FC
{indexPattern.title}
- {indexPattern.title}
+
+
+
+
+
+
+
+
+
+
+ {title}
- {title}
+
-
+
= RequestHandler
extends (...a: infer U) => infer R ? (user: ReportingUser, ...a: U) => R : never; @@ -21,7 +21,7 @@ export const authorizedUserPreRoutingFactory = function authorizedUserPreRouting ) { const setupDeps = reporting.getPluginSetupDeps(); const getUser = getUserFactory(setupDeps.security); - return
(handler: RequestHandlerUser): RequestHandler
=> { + return
(handler: RequestHandlerUser
): RequestHandler
=> {
return (context, req, res) => {
let user: ReportingUser = null;
if (setupDeps.security && setupDeps.security.license.isEnabled()) {
diff --git a/x-pack/plugins/security_solution/common/machine_learning/has_ml_license.test.ts b/x-pack/plugins/security_solution/common/machine_learning/has_ml_license.test.ts
new file mode 100644
index 0000000000000..1ffc2e16b78f7
--- /dev/null
+++ b/x-pack/plugins/security_solution/common/machine_learning/has_ml_license.test.ts
@@ -0,0 +1,20 @@
+/*
+ * 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 { emptyMlCapabilities } from './empty_ml_capabilities';
+import { hasMlLicense } from './has_ml_license';
+
+describe('hasMlLicense', () => {
+ test('it returns false when license is not platinum or trial', () => {
+ const capabilities = { ...emptyMlCapabilities, isPlatinumOrTrialLicense: false };
+ expect(hasMlLicense(capabilities)).toEqual(false);
+ });
+
+ test('it returns true when license is platinum or trial', () => {
+ const capabilities = { ...emptyMlCapabilities, isPlatinumOrTrialLicense: true };
+ expect(hasMlLicense(capabilities)).toEqual(true);
+ });
+});
diff --git a/x-pack/plugins/security_solution/common/machine_learning/has_ml_license.ts b/x-pack/plugins/security_solution/common/machine_learning/has_ml_license.ts
new file mode 100644
index 0000000000000..c0b6862ac30fe
--- /dev/null
+++ b/x-pack/plugins/security_solution/common/machine_learning/has_ml_license.ts
@@ -0,0 +1,10 @@
+/*
+ * 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 { MlCapabilitiesResponse } from '../../../ml/common/types/capabilities';
+
+export const hasMlLicense = (capabilities: MlCapabilitiesResponse): boolean =>
+ capabilities.isPlatinumOrTrialLicense;
diff --git a/x-pack/plugins/security_solution/common/machine_learning/is_security_job.ts b/x-pack/plugins/security_solution/common/machine_learning/is_security_job.ts
index 43cfa4ad59964..f5783fc9b3973 100644
--- a/x-pack/plugins/security_solution/common/machine_learning/is_security_job.ts
+++ b/x-pack/plugins/security_solution/common/machine_learning/is_security_job.ts
@@ -4,8 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { MlSummaryJob } from '../../../ml/common/types/anomaly_detection_jobs';
import { ML_GROUP_IDS } from '../constants';
-export const isSecurityJob = (job: MlSummaryJob): boolean =>
+export const isSecurityJob = (job: { groups: string[] }): boolean =>
job.groups.some((group) => ML_GROUP_IDS.includes(group));
diff --git a/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts b/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts
index 6fbb308672e5d..e6597de892bff 100644
--- a/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts
+++ b/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts
@@ -9,13 +9,11 @@ import { useState, useEffect, useMemo } from 'react';
import { DEFAULT_ANOMALY_SCORE } from '../../../../../common/constants';
import { anomaliesTableData } from '../api/anomalies_table_data';
import { InfluencerInput, Anomalies, CriteriaFields } from '../types';
-import { hasMlUserPermissions } from '../../../../../common/machine_learning/has_ml_user_permissions';
-import { useSiemJobs } from '../../ml_popover/hooks/use_siem_jobs';
-import { useMlCapabilities } from '../../ml_popover/hooks/use_ml_capabilities';
-import { useStateToaster, errorToToaster } from '../../toasters';
import * as i18n from './translations';
import { useTimeZone, useUiSetting$ } from '../../../lib/kibana';
+import { useAppToasts } from '../../../hooks/use_app_toasts';
+import { useInstalledSecurityJobs } from '../hooks/use_installed_security_jobs';
interface Args {
influencers?: InfluencerInput[];
@@ -58,15 +56,13 @@ export const useAnomaliesTableData = ({
skip = false,
}: Args): Return => {
const [tableData, setTableData] = useState