From e9b43cdd3f718f83fa54a381dbfbe914ad3f5f2e Mon Sep 17 00:00:00 2001 From: Zacqary Adam Xeper Date: Mon, 4 Jan 2021 14:52:20 -0600 Subject: [PATCH 01/32] [Metrics UI] Fix Process List layout issues (#87005) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../tabs/processes/process_row.tsx | 20 +++-- .../tabs/processes/process_row_charts.tsx | 2 +- .../tabs/processes/processes_table.tsx | 12 ++- .../tabs/processes/summary_table.tsx | 80 +++++++++---------- 4 files changed, 61 insertions(+), 53 deletions(-) diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/process_row.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/process_row.tsx index 4718ed09dc9b2..3f0798c4a1670 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/process_row.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/process_row.tsx @@ -51,7 +51,7 @@ export const ProcessRow = ({ cells, item }: Props) => { {({ measureRef, bounds: { height = 0 } }) => ( - +
@@ -81,7 +81,7 @@ export const ProcessRow = ({ cells, item }: Props) => { )} - + {i18n.translate( @@ -92,7 +92,7 @@ export const ProcessRow = ({ cells, item }: Props) => { )} - {item.pid} + {item.pid} @@ -105,12 +105,12 @@ export const ProcessRow = ({ cells, item }: Props) => { )} - {item.user} + {item.user} - + )} @@ -120,11 +120,15 @@ export const ProcessRow = ({ cells, item }: Props) => { ); }; -export const CodeLine = euiStyled(EuiCode).attrs({ +const ExpandedRowDescriptionList = euiStyled(EuiDescriptionList).attrs({ + compressed: true, +})` + width: 100%; +`; + +const CodeListItem = euiStyled(EuiCode).attrs({ transparentBackground: true, })` - text-overflow: ellipsis; - overflow: hidden; padding: 0 !important; & code.euiCodeBlock__code { white-space: nowrap !important; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/process_row_charts.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/process_row_charts.tsx index 7b7a285b5d6b8..af515ae75854c 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/process_row_charts.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/process_row_charts.tsx @@ -138,7 +138,7 @@ const ProcessChart = ({ timeseries, color, label }: ProcessChartProps) => { }; const ChartContainer = euiStyled.div` - width: 300px; + width: 100%; height: 140px; `; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/processes_table.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/processes_table.tsx index 3e4b066afa157..1ea6e397e7768 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/processes_table.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/processes_table.tsx @@ -28,7 +28,7 @@ import { FORMATTERS } from '../../../../../../../../common/formatters'; import { euiStyled } from '../../../../../../../../../observability/public'; import { SortBy } from '../../../../hooks/use_process_list'; import { Process } from './types'; -import { ProcessRow, CodeLine } from './process_row'; +import { ProcessRow } from './process_row'; import { StateBadge } from './state_badge'; import { STATE_ORDER } from './states'; @@ -150,7 +150,7 @@ export const ProcessesTable = ({ return ( <> - + {columns.map((column) => ( @@ -296,3 +296,11 @@ const columns: Array<{ render: (value: number) => FORMATTERS.percent(value), }, ]; + +const CodeLine = euiStyled.div` + font-family: ${(props) => props.theme.eui.euiCodeFontFamily}; + font-size: ${(props) => props.theme.eui.euiFontSizeS}; + white-space: pre; + overflow: hidden; + text-overflow: ellipsis; +`; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/summary_table.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/summary_table.tsx index 6efabf1b8c0ae..5bbba906b62f2 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/summary_table.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/summary_table.tsx @@ -7,7 +7,15 @@ import React, { useMemo } from 'react'; import { mapValues } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { EuiBasicTable, EuiLoadingSpinner, EuiBasicTableColumn } from '@elastic/eui'; +import { + EuiLoadingSpinner, + EuiFlexGroup, + EuiFlexItem, + EuiDescriptionList, + EuiDescriptionListTitle, + EuiDescriptionListDescription, + EuiHorizontalRule, +} from '@elastic/eui'; import { euiStyled } from '../../../../../../../../../observability/public'; import { ProcessListAPIResponse } from '../../../../../../../../common/http_api'; import { STATE_NAMES } from './states'; @@ -17,63 +25,51 @@ interface Props { isLoading: boolean; } -type SummaryColumn = { +type SummaryRecord = { total: number; } & Record; export const SummaryTable = ({ processSummary, isLoading }: Props) => { const processCount = useMemo( () => - [ - { - total: isLoading ? -1 : processSummary.total, - ...mapValues(STATE_NAMES, () => (isLoading ? -1 : 0)), - ...(isLoading ? {} : processSummary), - }, - ] as SummaryColumn[], + ({ + total: isLoading ? -1 : processSummary.total, + ...mapValues(STATE_NAMES, () => (isLoading ? -1 : 0)), + ...(isLoading ? {} : processSummary), + } as SummaryRecord), [processSummary, isLoading] ); return ( - - - + <> + + {Object.entries(processCount).map(([field, value]) => ( + + + {columnTitles[field as keyof SummaryRecord]} + + {value === -1 ? : value} + + + + ))} + + + ); }; -const loadingRenderer = (value: number) => (value === -1 ? : value); - -const columns = [ - { - field: 'total', - name: i18n.translate('xpack.infra.metrics.nodeDetails.processes.headingTotalProcesses', { - defaultMessage: 'Total processes', - }), - width: 125, - render: loadingRenderer, - }, - ...Object.entries(STATE_NAMES).map(([field, name]) => ({ field, name, render: loadingRenderer })), -] as Array>; +const columnTitles = { + total: i18n.translate('xpack.infra.metrics.nodeDetails.processes.headingTotalProcesses', { + defaultMessage: 'Total processes', + }), + ...STATE_NAMES, +}; const LoadingSpinner = euiStyled(EuiLoadingSpinner).attrs({ size: 'm' })` margin-top: 2px; margin-bottom: 3px; `; -const StyleWrapper = euiStyled.div` - & .euiTableHeaderCell { - border-bottom: none; - & .euiTableCellContent { - padding-bottom: 0; - } - & .euiTableCellContent__text { - font-size: ${(props) => props.theme.eui.euiFontSizeS}; - } - } - - & .euiTableRowCell { - border-top: none; - & .euiTableCellContent { - padding-top: 0; - } - } +const ColumnTitle = euiStyled(EuiDescriptionListTitle)` + white-space: nowrap; `; From e8ecbc77a9538f2782fc7ba774f0bbf7beb6246a Mon Sep 17 00:00:00 2001 From: Spencer Date: Mon, 4 Jan 2021 14:01:30 -0700 Subject: [PATCH 02/32] [dev/cli] stop trimming log lines from the server (#87199) Co-authored-by: spalger --- src/dev/cli_dev_mode/log.ts | 10 +++++----- src/dev/cli_dev_mode/optimizer.test.ts | 4 ++-- src/dev/cli_dev_mode/optimizer.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/dev/cli_dev_mode/log.ts b/src/dev/cli_dev_mode/log.ts index f349026ca9cab..3a5d60e65c3f1 100644 --- a/src/dev/cli_dev_mode/log.ts +++ b/src/dev/cli_dev_mode/log.ts @@ -25,7 +25,7 @@ export interface Log { good(label: string, ...args: any[]): void; warn(label: string, ...args: any[]): void; bad(label: string, ...args: any[]): void; - write(label: string, ...args: any[]): void; + write(...args: any[]): void; } export class CliLog implements Log { @@ -58,9 +58,9 @@ export class CliLog implements Log { console.log(Chalk.white.bgRed(` ${label.trim()} `), ...args); } - write(label: string, ...args: any[]) { + write(...args: any[]) { // eslint-disable-next-line no-console - console.log(` ${label.trim()} `, ...args); + console.log(...args); } } @@ -88,10 +88,10 @@ export class TestLog implements Log { }); } - write(label: string, ...args: any[]) { + write(...args: any[]) { this.messages.push({ type: 'write', - args: [label, ...args], + args, }); } } diff --git a/src/dev/cli_dev_mode/optimizer.test.ts b/src/dev/cli_dev_mode/optimizer.test.ts index 8a82012499b33..6017ab2c35d0f 100644 --- a/src/dev/cli_dev_mode/optimizer.test.ts +++ b/src/dev/cli_dev_mode/optimizer.test.ts @@ -191,8 +191,8 @@ it('is ready when optimizer phase is success or issue and logs in familiar forma const lines = await linesPromise; expect(lines).toMatchInlineSnapshot(` Array [ - "np bld log [timestamp] [success][@kbn/optimizer] 0 bundles compiled successfully after 0 sec", - "np bld log [timestamp] [error][@kbn/optimizer] webpack compile errors", + " np bld log [timestamp] [success][@kbn/optimizer] 0 bundles compiled successfully after 0 sec", + " np bld log [timestamp] [error][@kbn/optimizer] webpack compile errors", ] `); }); diff --git a/src/dev/cli_dev_mode/optimizer.ts b/src/dev/cli_dev_mode/optimizer.ts index 9aac414f02b29..f618a0fdbe72f 100644 --- a/src/dev/cli_dev_mode/optimizer.ts +++ b/src/dev/cli_dev_mode/optimizer.ts @@ -105,7 +105,7 @@ export class Optimizer { ToolingLogTextWriter.write( options.writeLogTo ?? process.stdout, - `${dim} log [${time()}] [${level(msg.type)}][${name}] `, + ` ${dim} log [${time()}] [${level(msg.type)}][${name}] `, msg ); return true; From afc2c51f43fef305e98a1ccbec8ece6558fe295f Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Mon, 4 Jan 2021 22:14:48 +0100 Subject: [PATCH 03/32] Bump Node.js from version 14.15.3 to 14.15.4 (#87207) --- .node-version | 2 +- .nvmrc | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.node-version b/.node-version index 19c4c189d3640..c91434ab584a7 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -14.15.3 +14.15.4 diff --git a/.nvmrc b/.nvmrc index 19c4c189d3640..c91434ab584a7 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -14.15.3 +14.15.4 diff --git a/package.json b/package.json index 00471d9c6ebf8..b657c8273517a 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "**/typescript": "4.1.2" }, "engines": { - "node": "14.15.3", + "node": "14.15.4", "yarn": "^1.21.1" }, "dependencies": { From 8b2690723b927ef9af4e3dc8db83dc6da4f329ec Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Mon, 4 Jan 2021 14:17:56 -0700 Subject: [PATCH 04/32] Migrates security solution usage collector es client from legacy to new (#86853) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/usage/collector.ts | 4 +-- .../usage/detections/detections.test.ts | 30 +++++------------ .../usage/detections/detections_helpers.ts | 32 +++++++++++++++---- .../server/usage/detections/index.ts | 6 ++-- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/x-pack/plugins/security_solution/server/usage/collector.ts b/x-pack/plugins/security_solution/server/usage/collector.ts index f4c5462267920..0d44ab42d8044 100644 --- a/x-pack/plugins/security_solution/server/usage/collector.ts +++ b/x-pack/plugins/security_solution/server/usage/collector.ts @@ -78,12 +78,12 @@ export const registerCollector: RegisterCollector = ({ }, }, isReady: () => kibanaIndex.length > 0, - fetch: async ({ callCluster }: CollectorFetchContext): Promise => { + fetch: async ({ esClient }: CollectorFetchContext): Promise => { const savedObjectsClient = await getInternalSavedObjectsClient(core); const [detections, endpoints] = await Promise.allSettled([ fetchDetectionsUsage( kibanaIndex, - callCluster, + esClient, ml, (savedObjectsClient as unknown) as SavedObjectsClientContract ), diff --git a/x-pack/plugins/security_solution/server/usage/detections/detections.test.ts b/x-pack/plugins/security_solution/server/usage/detections/detections.test.ts index 0d2d610c53cdc..f60f863414b2f 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/detections.test.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/detections.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LegacyAPICaller, SavedObjectsClientContract } from '../../../../../../src/core/server'; +import { ElasticsearchClient, SavedObjectsClientContract } from '../../../../../../src/core/server'; import { elasticsearchServiceMock } from '../../../../../../src/core/server/mocks'; import { mlServicesMock } from '../../lib/machine_learning/mocks'; import { @@ -16,22 +16,17 @@ import { fetchDetectionsUsage } from './index'; describe('Detections Usage', () => { describe('fetchDetectionsUsage()', () => { - let callClusterMock: jest.Mocked; + let esClientMock: jest.Mocked; let savedObjectsClientMock: jest.Mocked; let mlMock: ReturnType; beforeEach(() => { - callClusterMock = elasticsearchServiceMock.createLegacyClusterClient().callAsInternalUser; + esClientMock = elasticsearchServiceMock.createClusterClient().asInternalUser; mlMock = mlServicesMock.create(); }); it('returns zeroed counts if both calls are empty', async () => { - const result = await fetchDetectionsUsage( - '', - callClusterMock, - mlMock, - savedObjectsClientMock - ); + const result = await fetchDetectionsUsage('', esClientMock, mlMock, savedObjectsClientMock); expect(result).toEqual({ detection_rules: { @@ -58,13 +53,9 @@ describe('Detections Usage', () => { }); it('tallies rules data given rules results', async () => { - (callClusterMock as jest.Mock).mockResolvedValue(getMockRulesResponse()); - const result = await fetchDetectionsUsage( - '', - callClusterMock, - mlMock, - savedObjectsClientMock - ); + (esClientMock.search as jest.Mock).mockResolvedValue({ body: getMockRulesResponse() }); + + const result = await fetchDetectionsUsage('', esClientMock, mlMock, savedObjectsClientMock); expect(result).toEqual( expect.objectContaining({ @@ -92,12 +83,7 @@ describe('Detections Usage', () => { jobsSummary: mockJobSummary, }); - const result = await fetchDetectionsUsage( - '', - callClusterMock, - mlMock, - savedObjectsClientMock - ); + const result = await fetchDetectionsUsage('', esClientMock, mlMock, savedObjectsClientMock); expect(result).toEqual( expect.objectContaining({ diff --git a/x-pack/plugins/security_solution/server/usage/detections/detections_helpers.ts b/x-pack/plugins/security_solution/server/usage/detections/detections_helpers.ts index 1a0e821ba47bc..804ea878108f3 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/detections_helpers.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/detections_helpers.ts @@ -4,12 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SearchParams } from 'elasticsearch'; - import { - LegacyAPICaller, + ElasticsearchClient, SavedObjectsClientContract, KibanaRequest, + SearchResponse, } from '../../../../../../src/core/server'; import { MlPluginSetup } from '../../../../ml/server'; import { SIGNALS_ID, INTERNAL_IMMUTABLE_KEY } from '../../../common/constants'; @@ -22,6 +21,26 @@ interface DetectionsMetric { isEnabled: boolean; } +interface RuleSearchBody { + query: { + bool: { + filter: { + term: { [key: string]: string }; + }; + }; + }; +} +interface RuleSearchParams { + body: RuleSearchBody; + filterPath: string[]; + ignoreUnavailable: boolean; + index: string; + size: number; +} +interface RuleSearchResult { + alert: { enabled: boolean; tags: string[] }; +} + const isElasticRule = (tags: string[]) => tags.includes(`${INTERNAL_IMMUTABLE_KEY}:true`); /** @@ -135,10 +154,10 @@ const updateMlJobsUsage = (jobMetric: DetectionsMetric, usage: MlJobsUsage): MlJ export const getRulesUsage = async ( index: string, - callCluster: LegacyAPICaller + esClient: ElasticsearchClient ): Promise => { let rulesUsage: DetectionRulesUsage = initialRulesUsage; - const ruleSearchOptions: SearchParams = { + const ruleSearchOptions: RuleSearchParams = { body: { query: { bool: { filter: { term: { 'alert.alertTypeId': SIGNALS_ID } } } } }, filterPath: ['hits.hits._source.alert.enabled', 'hits.hits._source.alert.tags'], ignoreUnavailable: true, @@ -147,8 +166,7 @@ export const getRulesUsage = async ( }; try { - const ruleResults = await callCluster<{ alert: { enabled: boolean; tags: string[] } }>( - 'search', + const { body: ruleResults } = await esClient.search>( ruleSearchOptions ); diff --git a/x-pack/plugins/security_solution/server/usage/detections/index.ts b/x-pack/plugins/security_solution/server/usage/detections/index.ts index 1f43d3186f2fd..63e28f3c66009 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/index.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LegacyAPICaller, SavedObjectsClientContract } from '../../../../../../src/core/server'; +import { ElasticsearchClient, SavedObjectsClientContract } from '../../../../../../src/core/server'; import { getMlJobsUsage, getRulesUsage, @@ -40,12 +40,12 @@ export const defaultDetectionsUsage = { export const fetchDetectionsUsage = async ( kibanaIndex: string, - callCluster: LegacyAPICaller, + esClient: ElasticsearchClient, ml: MlPluginSetup | undefined, savedObjectClient: SavedObjectsClientContract ): Promise => { const [rulesUsage, mlJobsUsage] = await Promise.allSettled([ - getRulesUsage(kibanaIndex, callCluster), + getRulesUsage(kibanaIndex, esClient), getMlJobsUsage(ml, savedObjectClient), ]); From 284f4226427ccba5a64d070136d6deb13b06e629 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Mon, 4 Jan 2021 14:21:20 -0700 Subject: [PATCH 05/32] Set containment alert recovery action group to 'No longer contained' (#87182) --- .../server/alert_types/geo_containment/alert_type.ts | 6 ++++++ .../alert_types/geo_containment/tests/alert_type.test.ts | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts index 85dcf1125becd..0d8628d00df85 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts @@ -160,6 +160,12 @@ export function getAlertType(logger: Logger): GeoContainmentAlertType { id: GEO_CONTAINMENT_ID, name: alertTypeName, actionGroups: [{ id: ActionGroupId, name: actionGroupName }], + recoveryActionGroup: { + id: 'notGeoContained', + name: i18n.translate('xpack.stackAlerts.geoContainment.notGeoContained', { + defaultMessage: 'No longer contained', + }), + }, defaultActionGroupId: ActionGroupId, executor: getGeoContainmentExecutor(logger), producer: STACK_ALERTS_FEATURE_ID, diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/alert_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/alert_type.test.ts index 0592c944de570..98842c8cc2cba 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/alert_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/alert_type.test.ts @@ -18,6 +18,10 @@ describe('alertType', () => { expect(alertType.actionGroups).toEqual([ { id: 'Tracked entity contained', name: 'Tracking containment met' }, ]); + expect(alertType.recoveryActionGroup).toEqual({ + id: 'notGeoContained', + name: 'No longer contained', + }); expect(alertType.actionVariables).toMatchSnapshot(); }); From e3856a9e45d01bf1dbc604809adcdb3f929e45d1 Mon Sep 17 00:00:00 2001 From: Spencer Date: Mon, 4 Jan 2021 15:46:37 -0700 Subject: [PATCH 06/32] [security/apiKeys] migrate from `id` to `ids` in ES request (#87053) Co-authored-by: spalger Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../alerts/server/invalidate_pending_api_keys/task.ts | 1 + .../server/authentication/api_keys/api_keys.test.ts | 10 +++++----- .../server/authentication/api_keys/api_keys.ts | 6 +++--- .../security/server/routes/api_keys/invalidate.test.ts | 10 +++++----- .../security/server/routes/api_keys/invalidate.ts | 2 +- x-pack/test/api_integration/apis/security/api_keys.ts | 3 +-- .../test/fleet_api_integration/apis/agents/unenroll.ts | 3 +-- x-pack/test/functional/apps/api_keys/home_page.ts | 3 +-- 8 files changed, 18 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/alerts/server/invalidate_pending_api_keys/task.ts b/x-pack/plugins/alerts/server/invalidate_pending_api_keys/task.ts index 91c3f5954d6d0..1c7320d3df6f3 100644 --- a/x-pack/plugins/alerts/server/invalidate_pending_api_keys/task.ts +++ b/x-pack/plugins/alerts/server/invalidate_pending_api_keys/task.ts @@ -193,6 +193,7 @@ async function invalidateApiKeys( encryptedSavedObjectsClient: EncryptedSavedObjectsClient, securityPluginStart?: SecurityPluginStart ) { + // TODO: This could probably send a single request to ES now that the invalidate API supports multiple ids in a single request let totalInvalidated = 0; await Promise.all( apiKeysToInvalidate.saved_objects.map(async (apiKeyObj) => { diff --git a/x-pack/plugins/security/server/authentication/api_keys/api_keys.test.ts b/x-pack/plugins/security/server/authentication/api_keys/api_keys.test.ts index 1e5d3baab83e6..c43ed9e1248f6 100644 --- a/x-pack/plugins/security/server/authentication/api_keys/api_keys.test.ts +++ b/x-pack/plugins/security/server/authentication/api_keys/api_keys.test.ts @@ -115,7 +115,7 @@ describe('API Keys', () => { expect(result).toEqual(true); expect(mockClusterClient.asInternalUser.security.invalidateApiKey).toHaveBeenCalledWith({ body: { - id: 'kibana-api-key-service-test', + ids: ['kibana-api-key-service-test'], }, }); }); @@ -318,7 +318,7 @@ describe('API Keys', () => { }); expect(mockScopedClusterClient.asCurrentUser.security.invalidateApiKey).toHaveBeenCalledWith({ body: { - id: '123', + ids: ['123'], }, }); }); @@ -345,7 +345,7 @@ describe('API Keys', () => { }); expect(mockScopedClusterClient.asCurrentUser.security.invalidateApiKey).toHaveBeenCalledWith({ body: { - id: '123', + ids: ['123'], }, }); }); @@ -378,7 +378,7 @@ describe('API Keys', () => { }); expect(mockClusterClient.asInternalUser.security.invalidateApiKey).toHaveBeenCalledWith({ body: { - id: '123', + ids: ['123'], }, }); }); @@ -405,7 +405,7 @@ describe('API Keys', () => { }); expect(mockClusterClient.asInternalUser.security.invalidateApiKey).toHaveBeenCalledWith({ body: { - id: '123', + ids: ['123'], }, }); }); diff --git a/x-pack/plugins/security/server/authentication/api_keys/api_keys.ts b/x-pack/plugins/security/server/authentication/api_keys/api_keys.ts index 212b5755549f9..a42efb678fcea 100644 --- a/x-pack/plugins/security/server/authentication/api_keys/api_keys.ts +++ b/x-pack/plugins/security/server/authentication/api_keys/api_keys.ts @@ -143,7 +143,7 @@ export class APIKeys { ); try { - await this.clusterClient.asInternalUser.security.invalidateApiKey({ body: { id } }); + await this.clusterClient.asInternalUser.security.invalidateApiKey({ body: { ids: [id] } }); return true; } catch (e) { if (this.doesErrorIndicateAPIKeysAreDisabled(e)) { @@ -240,7 +240,7 @@ export class APIKeys { await this.clusterClient .asScoped(request) .asCurrentUser.security.invalidateApiKey({ - body: { id: params.id }, + body: { ids: [params.id] }, }) ).body; this.logger.debug('API key was invalidated successfully as current user'); @@ -268,7 +268,7 @@ export class APIKeys { // Internal user needs `cluster:admin/xpack/security/api_key/invalidate` privilege to use this API result = ( await this.clusterClient.asInternalUser.security.invalidateApiKey({ - body: { id: params.id }, + body: { ids: [params.id] }, }) ).body; this.logger.debug('API key was invalidated successfully'); diff --git a/x-pack/plugins/security/server/routes/api_keys/invalidate.test.ts b/x-pack/plugins/security/server/routes/api_keys/invalidate.test.ts index 9ac41fdfa7483..88a84462e8a66 100644 --- a/x-pack/plugins/security/server/routes/api_keys/invalidate.test.ts +++ b/x-pack/plugins/security/server/routes/api_keys/invalidate.test.ts @@ -127,7 +127,7 @@ describe('Invalidate API keys', () => { isAdmin: true, }, asserts: { - apiArguments: [{ body: { id: 'si8If24B1bKsmSLTAhJV' } }], + apiArguments: [{ body: { ids: ['si8If24B1bKsmSLTAhJV'] } }], statusCode: 200, result: { itemsInvalidated: [], @@ -151,7 +151,7 @@ describe('Invalidate API keys', () => { isAdmin: true, }, asserts: { - apiArguments: [{ body: { id: 'si8If24B1bKsmSLTAhJV' } }], + apiArguments: [{ body: { ids: ['si8If24B1bKsmSLTAhJV'] } }], statusCode: 200, result: { itemsInvalidated: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key' }], @@ -167,7 +167,7 @@ describe('Invalidate API keys', () => { isAdmin: false, }, asserts: { - apiArguments: [{ body: { id: 'si8If24B1bKsmSLTAhJV', owner: true } }], + apiArguments: [{ body: { ids: ['si8If24B1bKsmSLTAhJV'], owner: true } }], statusCode: 200, result: { itemsInvalidated: [{ id: 'si8If24B1bKsmSLTAhJV', name: 'my-api-key' }], @@ -192,8 +192,8 @@ describe('Invalidate API keys', () => { }, asserts: { apiArguments: [ - { body: { id: 'si8If24B1bKsmSLTAhJV' } }, - { body: { id: 'ab8If24B1bKsmSLTAhNC' } }, + { body: { ids: ['si8If24B1bKsmSLTAhJV'] } }, + { body: { ids: ['ab8If24B1bKsmSLTAhNC'] } }, ], statusCode: 200, result: { diff --git a/x-pack/plugins/security/server/routes/api_keys/invalidate.ts b/x-pack/plugins/security/server/routes/api_keys/invalidate.ts index 3977954197007..9e89b4593f023 100644 --- a/x-pack/plugins/security/server/routes/api_keys/invalidate.ts +++ b/x-pack/plugins/security/server/routes/api_keys/invalidate.ts @@ -33,7 +33,7 @@ export function defineInvalidateApiKeysRoutes({ router }: RouteDefinitionParams) await Promise.all( request.body.apiKeys.map(async (key) => { try { - const body: { id: string; owner?: boolean } = { id: key.id }; + const body: { ids: string[]; owner?: boolean } = { ids: [key.id] }; if (!request.body.isAdmin) { body.owner = true; } diff --git a/x-pack/test/api_integration/apis/security/api_keys.ts b/x-pack/test/api_integration/apis/security/api_keys.ts index 5622474c215c3..86ef1481c83e3 100644 --- a/x-pack/test/api_integration/apis/security/api_keys.ts +++ b/x-pack/test/api_integration/apis/security/api_keys.ts @@ -10,8 +10,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/87157 - describe.skip('API Keys', () => { + describe('API Keys', () => { describe('GET /internal/security/api_key/_enabled', () => { it('should indicate that API Keys are enabled', async () => { await supertest diff --git a/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts b/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts index b906c535a2b41..0c40797699c86 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts @@ -17,8 +17,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const esClient = getService('es'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/87166 - describe.skip('fleet_unenroll_agent', () => { + describe('fleet_unenroll_agent', () => { skipIfNoDockerRegistry(providerContext); let accessAPIKeyId: string; let outputAPIKeyId: string; diff --git a/x-pack/test/functional/apps/api_keys/home_page.ts b/x-pack/test/functional/apps/api_keys/home_page.ts index f94a1828b7a5a..39d8449218ffa 100644 --- a/x-pack/test/functional/apps/api_keys/home_page.ts +++ b/x-pack/test/functional/apps/api_keys/home_page.ts @@ -13,8 +13,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const security = getService('security'); const testSubjects = getService('testSubjects'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/87163 - describe.skip('Home page', function () { + describe('Home page', function () { before(async () => { await security.testUser.setRoles(['kibana_admin']); await pageObjects.common.navigateToApp('apiKeys'); From a0f330cc8c51e20a2ea90dd81a6f981064928839 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 4 Jan 2021 19:02:25 -0400 Subject: [PATCH 07/32] [Fleet] Handle errors happenning during Fleet setup in the UI (#87185) --- .../fleet/hooks/use_fleet_status.tsx | 3 ++- .../fleet/sections/agents/index.tsx | 20 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_fleet_status.tsx b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_fleet_status.tsx index 18bcb4539c740..2bb328a51c60a 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_fleet_status.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_fleet_status.tsx @@ -13,6 +13,7 @@ interface FleetStatusState { enabled: boolean; isLoading: boolean; isReady: boolean; + error?: Error; missingRequirements?: GetFleetStatusResponse['missing_requirements']; } @@ -44,7 +45,7 @@ export const FleetStatusProvider: React.FC = ({ children }) => { missingRequirements: res.data?.missing_requirements, })); } catch (error) { - setState((s) => ({ ...s, isLoading: true })); + setState((s) => ({ ...s, isLoading: false, error })); } } useEffect(() => { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx index 758131a9a4b7e..8c6163578617c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx @@ -4,9 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { HashRouter as Router, Route, Switch, Redirect } from 'react-router-dom'; import { PAGE_ROUTING_PATHS } from '../../constants'; -import { Loading } from '../../components'; +import { Loading, Error } from '../../components'; import { useConfig, useFleetStatus, useBreadcrumbs, useCapabilities } from '../../hooks'; import { AgentListPage } from './agent_list_page'; import { SetupPage } from './setup_page'; @@ -14,6 +15,7 @@ import { AgentDetailsPage } from './agent_details_page'; import { NoAccessPage } from './error_pages/no_access'; import { EnrollmentTokenListPage } from './enrollment_token_list_page'; import { ListLayout } from './components/list_layout'; +import { WithoutHeaderLayout } from '../../layouts'; export const FleetApp: React.FunctionComponent = () => { useBreadcrumbs('fleet'); @@ -27,6 +29,22 @@ export const FleetApp: React.FunctionComponent = () => { return ; } + if (fleetStatus.error) { + return ( + + + } + error={fleetStatus.error} + /> + + ); + } + if (fleetStatus.isReady === false) { return ( Date: Mon, 4 Jan 2021 18:23:11 -0500 Subject: [PATCH 08/32] Revert "[Fleet][EPM] Revert es-storage-related commits (#85942) (#86017)" (#87183) This reverts commit 70fbe91fb18c6a940d19d470240dc8abfb0a59de. --- x-pack/plugins/fleet/common/constants/epm.ts | 2 +- .../plugins/fleet/common/types/models/epm.ts | 6 + .../plugins/fleet/server/constants/index.ts | 1 + .../fleet/server/routes/epm/handlers.ts | 58 +++++--- .../fleet/server/saved_objects/index.ts | 27 ++++ .../server/services/epm/archive/storage.ts | 140 ++++++++++++++++++ .../services/epm/packages/_install_package.ts | 24 ++- .../ensure_installed_default_packages.test.ts | 1 + .../epm/packages/get_install_type.test.ts | 2 + .../server/services/epm/packages/install.ts | 1 + .../server/services/epm/packages/remove.ts | 5 +- .../common/endpoint/generate_data.ts | 1 + .../apis/epm/install_remove_assets.ts | 24 +++ .../apis/epm/update_assets.ts | 20 +++ 14 files changed, 290 insertions(+), 22 deletions(-) create mode 100644 x-pack/plugins/fleet/server/services/epm/archive/storage.ts diff --git a/x-pack/plugins/fleet/common/constants/epm.ts b/x-pack/plugins/fleet/common/constants/epm.ts index b94c2cd12cd5f..5ba4de914c724 100644 --- a/x-pack/plugins/fleet/common/constants/epm.ts +++ b/x-pack/plugins/fleet/common/constants/epm.ts @@ -3,8 +3,8 @@ * 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 PACKAGES_SAVED_OBJECT_TYPE = 'epm-packages'; +export const ASSETS_SAVED_OBJECT_TYPE = 'epm-packages-assets'; export const INDEX_PATTERN_SAVED_OBJECT_TYPE = 'index-pattern'; export const MAX_TIME_COMPLETE_INSTALL = 60000; diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index a9893b170492f..77625e48dbc96 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -8,6 +8,7 @@ // TODO: Update when https://github.com/elastic/kibana/issues/53021 is closed import { SavedObject, SavedObjectAttributes, SavedObjectReference } from 'src/core/public'; import { + ASSETS_SAVED_OBJECT_TYPE, agentAssetTypes, dataTypes, defaultPackages, @@ -268,6 +269,7 @@ export type PackageInfo = export interface Installation extends SavedObjectAttributes { installed_kibana: KibanaAssetReference[]; installed_es: EsAssetReference[]; + package_assets: PackageAssetReference[]; es_index_patterns: Record; name: string; version: string; @@ -297,6 +299,10 @@ export type EsAssetReference = Pick & { type: ElasticsearchAssetType; }; +export type PackageAssetReference = Pick & { + type: typeof ASSETS_SAVED_OBJECT_TYPE; +}; + export type RequiredPackage = typeof requiredPackages; export type DefaultPackages = typeof defaultPackages; diff --git a/x-pack/plugins/fleet/server/constants/index.ts b/x-pack/plugins/fleet/server/constants/index.ts index 5d00b96634214..dbf2fbc362a45 100644 --- a/x-pack/plugins/fleet/server/constants/index.ts +++ b/x-pack/plugins/fleet/server/constants/index.ts @@ -40,6 +40,7 @@ export { PACKAGE_POLICY_SAVED_OBJECT_TYPE, OUTPUT_SAVED_OBJECT_TYPE, PACKAGES_SAVED_OBJECT_TYPE, + ASSETS_SAVED_OBJECT_TYPE, INDEX_PATTERN_SAVED_OBJECT_TYPE, ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE, GLOBAL_SETTINGS_SAVED_OBJECT_TYPE, diff --git a/x-pack/plugins/fleet/server/routes/epm/handlers.ts b/x-pack/plugins/fleet/server/routes/epm/handlers.ts index cfcde99541f13..9ccf60dc80a5f 100644 --- a/x-pack/plugins/fleet/server/routes/epm/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/epm/handlers.ts @@ -41,12 +41,13 @@ import { removeInstallation, getLimitedPackages, getInstallationObject, + getInstallation, } from '../../services/epm/packages'; import { defaultIngestErrorHandler, ingestErrorToResponseOptions } from '../../errors'; import { splitPkgKey } from '../../services/epm/registry'; import { licenseService } from '../../services'; import { getArchiveEntry } from '../../services/epm/archive/cache'; -import { bufferToStream } from '../../services/epm/streams'; +import { getAsset } from '../../services/epm/archive/storage'; export const getCategoriesHandler: RequestHandler< undefined, @@ -107,32 +108,51 @@ export const getFileHandler: RequestHandler { + const { path, buffer, name, version, installSource } = opts; + const fileExt = extname(path); + const contentType = mime.lookup(fileExt); + const mediaType = mime.contentType(contentType || fileExt); + // can use to create a data URL like `data:${mediaType};base64,${base64Data}` + + const bufferIsBinary = await isBinaryFile(buffer); + const dataUtf8 = bufferIsBinary ? '' : buffer.toString('utf8'); + const dataBase64 = bufferIsBinary ? buffer.toString('base64') : ''; + + // validation: filesize? asset type? anything else + if (dataUtf8.length > MAX_ES_ASSET_BYTES) { + throw new Error(`File at ${path} is larger than maximum allowed size of ${MAX_ES_ASSET_BYTES}`); + } + + if (dataBase64.length > MAX_ES_ASSET_BYTES) { + throw new Error( + `After base64 encoding file at ${path} is larger than maximum allowed size of ${MAX_ES_ASSET_BYTES}` + ); + } + + return { + package_name: name, + package_version: version, + install_source: installSource, + asset_path: path, + media_type: mediaType || '', + data_utf8: dataUtf8, + data_base64: dataBase64, + }; +} + +export async function removeArchiveEntries(opts: { + savedObjectsClient: SavedObjectsClientContract; + refs: PackageAssetReference[]; +}) { + const { savedObjectsClient, refs } = opts; + const results = await Promise.all( + refs.map((ref) => savedObjectsClient.delete(ASSETS_SAVED_OBJECT_TYPE, ref.id)) + ); + return results; +} + +export async function saveArchiveEntries(opts: { + savedObjectsClient: SavedObjectsClientContract; + paths: string[]; + packageInfo: InstallablePackage; + installSource: InstallSource; +}) { + const { savedObjectsClient, paths, packageInfo, installSource } = opts; + const bulkBody = await Promise.all( + paths.map((path) => { + const buffer = getArchiveEntry(path); + if (!buffer) throw new Error(`Could not find ArchiveEntry at ${path}`); + const { name, version } = packageInfo; + return archiveEntryToBulkCreateObject({ path, buffer, name, version, installSource }); + }) + ); + + const results = await savedObjectsClient.bulkCreate(bulkBody); + return results; +} + +export async function archiveEntryToBulkCreateObject(opts: { + path: string; + buffer: Buffer; + name: string; + version: string; + installSource: InstallSource; +}): Promise> { + const { path, buffer, name, version, installSource } = opts; + const doc = await archiveEntryToESDocument({ path, buffer, name, version, installSource }); + return { + id: assetPathToObjectId(doc.asset_path), + type: ASSETS_SAVED_OBJECT_TYPE, + attributes: doc, + }; +} + +export async function getAsset(opts: { + savedObjectsClient: SavedObjectsClientContract; + path: string; +}) { + const { savedObjectsClient, path } = opts; + const assetSavedObject = await savedObjectsClient.get( + ASSETS_SAVED_OBJECT_TYPE, + assetPathToObjectId(path) + ); + const storedAsset = assetSavedObject?.attributes; + if (!storedAsset) { + return; + } + + return storedAsset; +} diff --git a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts index c7500a9cfeaf6..c0e2fcb12bcf8 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts @@ -5,7 +5,13 @@ */ import { SavedObject, SavedObjectsClientContract } from 'src/core/server'; -import { InstallablePackage, InstallSource, MAX_TIME_COMPLETE_INSTALL } from '../../../../common'; +import { + InstallablePackage, + InstallSource, + PackageAssetReference, + MAX_TIME_COMPLETE_INSTALL, + ASSETS_SAVED_OBJECT_TYPE, +} from '../../../../common'; import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../constants'; import { AssetReference, @@ -24,6 +30,7 @@ import { deleteKibanaSavedObjectsAssets } from './remove'; import { installTransform } from '../elasticsearch/transform/install'; import { createInstallation, saveKibanaAssetsRefs, updateVersion } from './install'; import { installIlmForDataStream } from '../elasticsearch/datastream_ilm/install'; +import { saveArchiveEntries } from '../archive/storage'; import { ConcurrentInstallOperationError } from '../../../errors'; // this is only exported for testing @@ -188,11 +195,26 @@ export async function _installPackage({ if (installKibanaAssetsError) throw installKibanaAssetsError; await Promise.all([installKibanaAssetsPromise, installIndexPatternPromise]); + const packageAssetResults = await saveArchiveEntries({ + savedObjectsClient, + paths, + packageInfo, + installSource, + }); + const packageAssetRefs: PackageAssetReference[] = packageAssetResults.saved_objects.map( + (result) => ({ + id: result.id, + type: ASSETS_SAVED_OBJECT_TYPE, + }) + ); + // update to newly installed version when all assets are successfully installed if (installedPkg) await updateVersion(savedObjectsClient, pkgName, pkgVersion); + await savedObjectsClient.update(PACKAGES_SAVED_OBJECT_TYPE, pkgName, { install_version: pkgVersion, install_status: 'installed', + package_assets: packageAssetRefs, }); return [ diff --git a/x-pack/plugins/fleet/server/services/epm/packages/ensure_installed_default_packages.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/ensure_installed_default_packages.test.ts index 4ad6fc96218de..fe7b8be23b03b 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/ensure_installed_default_packages.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/ensure_installed_default_packages.test.ts @@ -43,6 +43,7 @@ const mockInstallation: SavedObject = { id: 'test-pkg', installed_kibana: [{ type: KibanaSavedObjectType.dashboard, id: 'dashboard-1' }], installed_es: [{ type: ElasticsearchAssetType.ingestPipeline, id: 'pipeline' }], + package_assets: [], es_index_patterns: { pattern: 'pattern-name' }, name: 'test package', version: '1.0.0', diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get_install_type.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/get_install_type.test.ts index a41511260c6e7..2dcfc7949d5e5 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get_install_type.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get_install_type.test.ts @@ -15,6 +15,7 @@ const mockInstallation: SavedObject = { id: 'test-pkg', installed_kibana: [{ type: KibanaSavedObjectType.dashboard, id: 'dashboard-1' }], installed_es: [{ type: ElasticsearchAssetType.ingestPipeline, id: 'pipeline' }], + package_assets: [], es_index_patterns: { pattern: 'pattern-name' }, name: 'test packagek', version: '1.0.0', @@ -32,6 +33,7 @@ const mockInstallationUpdateFail: SavedObject = { id: 'test-pkg', installed_kibana: [{ type: KibanaSavedObjectType.dashboard, id: 'dashboard-1' }], installed_es: [{ type: ElasticsearchAssetType.ingestPipeline, id: 'pipeline' }], + package_assets: [], es_index_patterns: { pattern: 'pattern-name' }, name: 'test packagek', version: '1.0.0', diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.ts index 48dd589dd0b8f..176bcf1381674 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.ts @@ -379,6 +379,7 @@ export async function createInstallation(options: { { installed_kibana: [], installed_es: [], + package_assets: [], es_index_patterns: toSaveESIndexPatterns, name: pkgName, version: pkgVersion, diff --git a/x-pack/plugins/fleet/server/services/epm/packages/remove.ts b/x-pack/plugins/fleet/server/services/epm/packages/remove.ts index 0b4a0faddf0cc..331b6bfa882da 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/remove.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/remove.ts @@ -24,6 +24,7 @@ import { packagePolicyService, appContextService } from '../..'; import { splitPkgKey } from '../registry'; import { deletePackageCache } from '../archive'; import { deleteIlms } from '../elasticsearch/datastream_ilm/remove'; +import { removeArchiveEntries } from '../archive/storage'; export async function removeInstallation(options: { savedObjectsClient: SavedObjectsClientContract; @@ -49,7 +50,7 @@ export async function removeInstallation(options: { `unable to remove package with existing package policy(s) in use by agent(s)` ); - // Delete the installed assets + // Delete the installed assets. Don't include installation.package_assets. Those are irrelevant to users const installedAssets = [...installation.installed_kibana, ...installation.installed_es]; await deleteAssets(installation, savedObjectsClient, callCluster); @@ -69,6 +70,8 @@ export async function removeInstallation(options: { version: pkgVersion, }); + await removeArchiveEntries({ savedObjectsClient, refs: installation.package_assets }); + // successful delete's in SO client return {}. return something more useful return installedAssets; } diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index 34c5ab0ded17b..fafd0c2772842 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -1332,6 +1332,7 @@ export class EndpointDocGenerator { { id: 'logs-endpoint.events.security', type: 'index_template' }, { id: 'metrics-endpoint.telemetry', type: 'index_template' }, ] as EsAssetReference[], + package_assets: [], es_index_patterns: { alerts: 'logs-endpoint.alerts-*', events: 'events-endpoint-*', diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts index 9dcd3ea100589..1d5f864c27eea 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts @@ -433,6 +433,7 @@ const expectAssetsInstalled = ({ ...res.attributes, installed_kibana: sortBy(res.attributes.installed_kibana, (o: AssetReference) => o.type), installed_es: sortBy(res.attributes.installed_es, (o: AssetReference) => o.type), + package_assets: sortBy(res.attributes.package_assets, (o: AssetReference) => o.type), }; expect(sortedRes).eql({ installed_kibana: [ @@ -495,6 +496,29 @@ const expectAssetsInstalled = ({ test_logs: 'logs-all_assets.test_logs-*', test_metrics: 'metrics-all_assets.test_metrics-*', }, + package_assets: [ + { id: '333a22a1-e639-5af5-ae62-907ffc83d603', type: 'epm-packages-assets' }, + { id: '256f3dad-6870-56c3-80a1-8dfa11e2d568', type: 'epm-packages-assets' }, + { id: '3fa0512f-bc01-5c2e-9df1-bc2f2a8259c8', type: 'epm-packages-assets' }, + { id: 'ea334ad8-80c2-5acd-934b-2a377290bf97', type: 'epm-packages-assets' }, + { id: '96c6eb85-fe2e-56c6-84be-5fda976796db', type: 'epm-packages-assets' }, + { id: '2d73a161-fa69-52d0-aa09-1bdc691b95bb', type: 'epm-packages-assets' }, + { id: '0a00c2d2-ce63-5b9c-9aa0-0cf1938f7362', type: 'epm-packages-assets' }, + { id: '691f0505-18c5-57a6-9f40-06e8affbdf7a', type: 'epm-packages-assets' }, + { id: 'b36e6dd0-58f7-5dd0-a286-8187e4019274', type: 'epm-packages-assets' }, + { id: 'f839c76e-d194-555a-90a1-3265a45789e4', type: 'epm-packages-assets' }, + { id: '9af7bbb3-7d8a-50fa-acc9-9dde6f5efca2', type: 'epm-packages-assets' }, + { id: '1e97a20f-9d1c-529b-8ff2-da4e8ba8bb71', type: 'epm-packages-assets' }, + { id: '8cfe0a2b-7016-5522-87e4-6d352360d1fc', type: 'epm-packages-assets' }, + { id: 'bd5ff3c5-655e-5385-9918-b60ff3040aad', type: 'epm-packages-assets' }, + { id: '0954ce3b-3165-5c1f-a4c0-56eb5f2fa487', type: 'epm-packages-assets' }, + { id: '60d6d054-57e4-590f-a580-52bf3f5e7cca', type: 'epm-packages-assets' }, + { id: '47758dc2-979d-5fbe-a2bd-9eded68a5a43', type: 'epm-packages-assets' }, + { id: '318959c9-997b-5a14-b328-9fc7355b4b74', type: 'epm-packages-assets' }, + { id: 'e786cbd9-0f3b-5a0b-82a6-db25145ebf58', type: 'epm-packages-assets' }, + { id: '53c94591-aa33-591d-8200-cd524c2a0561', type: 'epm-packages-assets' }, + { id: 'b658d2d4-752e-54b8-afc2-4c76155c1466', type: 'epm-packages-assets' }, + ], name: 'all_assets', version: '0.1.0', internal: false, diff --git a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts index d72209edf6501..7b264f949532e 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts @@ -322,6 +322,26 @@ export default function (providerContext: FtrProviderContext) { test_logs: 'logs-all_assets.test_logs-*', test_metrics: 'metrics-all_assets.test_metrics-*', }, + package_assets: [ + { id: '3eb4c54a-638f-51b6-84e2-d53f5a666e37', type: 'epm-packages-assets' }, + { id: '4acfbf69-7a27-5c58-9c99-7c86843d958f', type: 'epm-packages-assets' }, + { id: '938655df-b339-523c-a9e4-123c89c0e1e1', type: 'epm-packages-assets' }, + { id: 'eec4606c-dbfa-565b-8e9c-fce1e641f3fc', type: 'epm-packages-assets' }, + { id: 'ef67e7e0-dca3-5a62-a42a-745db5ad7c1f', type: 'epm-packages-assets' }, + { id: '64239d25-be40-5e10-94b5-f6b74b8c5474', type: 'epm-packages-assets' }, + { id: '071b5113-4c9f-5ee9-aafe-d098a4c066f6', type: 'epm-packages-assets' }, + { id: '498d8215-2613-5399-9a13-fa4f0bf513e2', type: 'epm-packages-assets' }, + { id: 'd2f87071-c866-503a-8fcb-7b23a8c7afbf', type: 'epm-packages-assets' }, + { id: '5a080eba-f482-545c-8695-6ccbd426b2a2', type: 'epm-packages-assets' }, + { id: '28523a82-1328-578d-84cb-800970560200', type: 'epm-packages-assets' }, + { id: 'cc1e3e1d-f27b-5d05-86f6-6e4b9a47c7dc', type: 'epm-packages-assets' }, + { id: '5c3aa147-089c-5084-beca-53c00e72ac80', type: 'epm-packages-assets' }, + { id: '48e582df-b1d2-5f88-b6ea-ba1fafd3a569', type: 'epm-packages-assets' }, + { id: 'bf3b0b65-9fdc-53c6-a9ca-e76140e56490', type: 'epm-packages-assets' }, + { id: '2e56f08b-1d06-55ed-abee-4708e1ccf0aa', type: 'epm-packages-assets' }, + { id: 'c7bf1a39-e057-58a0-afde-fb4b48751d8c', type: 'epm-packages-assets' }, + { id: '8c665f28-a439-5f43-b5fd-8fda7b576735', type: 'epm-packages-assets' }, + ], name: 'all_assets', version: '0.2.0', internal: false, From 8ac632b068a0b30d74880e7edb2617e6064d1061 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Mon, 4 Jan 2021 17:39:57 -0700 Subject: [PATCH 09/32] [data.search.session] Store search strategy in saved object for background sessions (#86057) * [data.search.session] Store search strategy in saved object * Update unit test to check strategy * Fix test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/data_enhanced/common/index.ts | 1 + .../common/search/session/types.ts | 7 ++- .../search/session/session_service.test.ts | 46 ++++++++++++++----- .../server/search/session/session_service.ts | 19 +++++--- .../api_integration/apis/search/session.ts | 5 +- 5 files changed, 58 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/data_enhanced/common/index.ts b/x-pack/plugins/data_enhanced/common/index.ts index 7b14a723d7877..f26ba0dd0b46c 100644 --- a/x-pack/plugins/data_enhanced/common/index.ts +++ b/x-pack/plugins/data_enhanced/common/index.ts @@ -15,4 +15,5 @@ export { BackgroundSessionSavedObjectAttributes, BackgroundSessionFindOptions, BackgroundSessionStatus, + BackgroundSessionSearchInfo, } from './search'; diff --git a/x-pack/plugins/data_enhanced/common/search/session/types.ts b/x-pack/plugins/data_enhanced/common/search/session/types.ts index 0b82c9160ea1a..1310c05ed6854 100644 --- a/x-pack/plugins/data_enhanced/common/search/session/types.ts +++ b/x-pack/plugins/data_enhanced/common/search/session/types.ts @@ -19,7 +19,12 @@ export interface BackgroundSessionSavedObjectAttributes { urlGeneratorId: string; initialState: Record; restoreState: Record; - idMapping: Record; + idMapping: Record; +} + +export interface BackgroundSessionSearchInfo { + id: string; // ID of the async search request + strategy: string; // Search strategy used to submit the search request } export interface BackgroundSessionFindOptions { diff --git a/x-pack/plugins/data_enhanced/server/search/session/session_service.test.ts b/x-pack/plugins/data_enhanced/server/search/session/session_service.test.ts index 766de908353f5..f14df97f00c12 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/session_service.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/session_service.test.ts @@ -30,6 +30,7 @@ describe('BackgroundSessionService', () => { const MOCK_SESSION_ID = 'session-id-mock'; const MOCK_ASYNC_ID = '123456'; + const MOCK_STRATEGY = 'ese'; const MOCK_KEY_HASH = '608de49a4600dbb5b173492759792e4a'; const createMockInternalSavedObjectClient = ( @@ -47,7 +48,10 @@ describe('BackgroundSessionService', () => { attributes: { sessionId: MOCK_SESSION_ID, idMapping: { - 'another-key': 'another-async-id', + 'another-key': { + id: 'another-async-id', + strategy: 'another-strategy', + }, }, }, id: MOCK_SESSION_ID, @@ -283,7 +287,7 @@ describe('BackgroundSessionService', () => { await service.trackId( searchRequest, searchId, - { sessionId, isStored }, + { sessionId, isStored, strategy: MOCK_STRATEGY }, { savedObjectsClient } ); @@ -313,7 +317,8 @@ describe('BackgroundSessionService', () => { ); const [setSessionId, setParams] = setSpy.mock.calls[0]; - expect(setParams.ids.get(requestHash)).toBe(searchId); + expect(setParams.ids.get(requestHash).id).toBe(searchId); + expect(setParams.ids.get(requestHash).strategy).toBe(MOCK_STRATEGY); expect(setSessionId).toBe(sessionId); }); @@ -326,12 +331,17 @@ describe('BackgroundSessionService', () => { await service.trackId( searchRequest, searchId, - { sessionId, isStored }, + { sessionId, isStored, strategy: MOCK_STRATEGY }, { savedObjectsClient } ); expect(savedObjectsClient.update).toHaveBeenCalledWith(BACKGROUND_SESSION_TYPE, sessionId, { - idMapping: { [requestHash]: searchId }, + idMapping: { + [requestHash]: { + id: searchId, + strategy: MOCK_STRATEGY, + }, + }, }); }); }); @@ -380,7 +390,12 @@ describe('BackgroundSessionService', () => { name: 'my_name', appId: 'my_app_id', urlGeneratorId: 'my_url_generator_id', - idMapping: { [requestHash]: searchId }, + idMapping: { + [requestHash]: { + id: searchId, + strategy: MOCK_STRATEGY, + }, + }, }, references: [], }; @@ -419,7 +434,10 @@ describe('BackgroundSessionService', () => { const findSpy = jest.fn().mockResolvedValue({ saved_objects: [] }); createMockInternalSavedObjectClient(findSpy); - const mockIdMapping = createMockIdMapping([[MOCK_KEY_HASH, MOCK_ASYNC_ID]], moment()); + const mockIdMapping = createMockIdMapping( + [[MOCK_KEY_HASH, { id: MOCK_ASYNC_ID, strategy: MOCK_STRATEGY }]], + moment() + ); Object.defineProperty(service, 'sessionSearchMap', { get: () => mockIdMapping, @@ -438,7 +456,7 @@ describe('BackgroundSessionService', () => { createMockInternalSavedObjectClient(findSpy); const mockIdMapping = createMockIdMapping( - [[MOCK_KEY_HASH, MOCK_ASYNC_ID]], + [[MOCK_KEY_HASH, { id: MOCK_ASYNC_ID, strategy: MOCK_STRATEGY }]], moment().subtract(2, 'm') ); @@ -459,7 +477,7 @@ describe('BackgroundSessionService', () => { createMockInternalSavedObjectClient(findSpy); const mockIdMapping = createMockIdMapping( - [[MOCK_KEY_HASH, MOCK_ASYNC_ID]], + [[MOCK_KEY_HASH, { id: MOCK_ASYNC_ID, strategy: MOCK_STRATEGY }]], moment(), MAX_UPDATE_RETRIES ); @@ -528,7 +546,10 @@ describe('BackgroundSessionService', () => { attributes: { idMapping: { b: 'c', - [MOCK_KEY_HASH]: MOCK_ASYNC_ID, + [MOCK_KEY_HASH]: { + id: MOCK_ASYNC_ID, + strategy: MOCK_STRATEGY, + }, }, }, }, @@ -566,7 +587,10 @@ describe('BackgroundSessionService', () => { id: MOCK_SESSION_ID, attributes: { idMapping: { - b: 'c', + b: { + id: 'c', + strategy: MOCK_STRATEGY, + }, }, }, }, diff --git a/x-pack/plugins/data_enhanced/server/search/session/session_service.ts b/x-pack/plugins/data_enhanced/server/search/session/session_service.ts index d426e73b48510..01291919001f5 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/session_service.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/session_service.ts @@ -32,6 +32,7 @@ import { import { BackgroundSessionSavedObjectAttributes, BackgroundSessionFindOptions, + BackgroundSessionSearchInfo, BackgroundSessionStatus, } from '../../../common'; import { BACKGROUND_SESSION_TYPE } from '../../saved_objects'; @@ -51,7 +52,7 @@ export interface BackgroundSessionDependencies { export interface SessionInfo { insertTime: Moment; retryCount: number; - ids: Map; + ids: Map; } export class BackgroundSessionService implements ISessionService { @@ -316,25 +317,31 @@ export class BackgroundSessionService implements ISessionService { public trackId = async ( searchRequest: IKibanaSearchRequest, searchId: string, - { sessionId, isStored }: ISearchOptions, + { sessionId, isStored, strategy }: ISearchOptions, deps: BackgroundSessionDependencies ) => { if (!sessionId || !searchId) return; this.logger.debug(`trackId | ${sessionId} | ${searchId}`); const requestHash = createRequestHash(searchRequest.params); + const searchInfo = { + id: searchId, + strategy: strategy!, + }; // If there is already a saved object for this session, update it to include this request/ID. // Otherwise, just update the in-memory mapping for this session for when the session is saved. if (isStored) { - const attributes = { idMapping: { [requestHash]: searchId } }; + const attributes = { + idMapping: { [requestHash]: searchInfo }, + }; await this.update(sessionId, attributes, deps); } else { const map = this.sessionSearchMap.get(sessionId) ?? { insertTime: moment(), retryCount: 0, - ids: new Map(), + ids: new Map(), }; - map.ids.set(requestHash, searchId); + map.ids.set(requestHash, searchInfo); this.sessionSearchMap.set(sessionId, map); } }; @@ -363,7 +370,7 @@ export class BackgroundSessionService implements ISessionService { throw new Error('No search ID in this session matching the given search request'); } - return session.attributes.idMapping[requestHash]; + return session.attributes.idMapping[requestHash].id; }; public asScopedProvider = ({ savedObjects }: CoreStart) => { diff --git a/x-pack/test/api_integration/apis/search/session.ts b/x-pack/test/api_integration/apis/search/session.ts index 992f25d1f09c7..ee2e4337adc95 100644 --- a/x-pack/test/api_integration/apis/search/session.ts +++ b/x-pack/test/api_integration/apis/search/session.ts @@ -119,8 +119,9 @@ export default function ({ getService }: FtrProviderContext) { const { idMapping } = resp.body.attributes; - expect(Object.values(idMapping)).to.contain(id1); - expect(Object.values(idMapping)).to.contain(id2); + const idMappings = Object.values(idMapping).map((value: any) => value.id); + expect(idMappings).to.contain(id1); + expect(idMappings).to.contain(id2); }); }); }); From 42ba5a8e9f98ad8c0d1fc4331ee69a7393c6e016 Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Mon, 4 Jan 2021 18:40:10 -0600 Subject: [PATCH 10/32] Toggle action and service icon menus (#87220) Make it so clicking the icon menu or action menu while the popover is open closes the popover. This also fixes the issue where the action menu would not close at all. Rename the `onOpen` prop to `onClick` to match what it does. Fixes #87161. Fixes #87131. --- .../app/service_details/service_icons/icon_popover.tsx | 6 +++--- .../app/service_details/service_icons/index.tsx | 6 ++++-- .../TransactionActionMenu/TransactionActionMenu.tsx | 8 +++++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/service_details/service_icons/icon_popover.tsx b/x-pack/plugins/apm/public/components/app/service_details/service_icons/icon_popover.tsx index fa890260a3060..5fe371c33475a 100644 --- a/x-pack/plugins/apm/public/components/app/service_details/service_icons/icon_popover.tsx +++ b/x-pack/plugins/apm/public/components/app/service_details/service_icons/icon_popover.tsx @@ -17,7 +17,7 @@ import { px } from '../../../../style/variables'; interface IconPopoverProps { title: string; children: React.ReactChild; - onOpen: () => void; + onClick: () => void; onClose: () => void; detailsFetchStatus: FETCH_STATUS; isOpen: boolean; @@ -27,7 +27,7 @@ export function IconPopover({ icon, title, children, - onOpen, + onClick, onClose, detailsFetchStatus, isOpen, @@ -44,7 +44,7 @@ export function IconPopover({ anchorPosition="downCenter" ownFocus={false} button={ - + } diff --git a/x-pack/plugins/apm/public/components/app/service_details/service_icons/index.tsx b/x-pack/plugins/apm/public/components/app/service_details/service_icons/index.tsx index 52a1958d78deb..f6a712c562bff 100644 --- a/x-pack/plugins/apm/public/components/app/service_details/service_icons/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_details/service_icons/index.tsx @@ -144,8 +144,10 @@ export function ServiceIcons({ serviceName }: Props) { icon={item.icon} detailsFetchStatus={detailsFetchStatus} title={item.title} - onOpen={() => { - setSelectedIconPopover(item.key); + onClick={() => { + setSelectedIconPopover((prevSelectedIconPopover) => + item.key === prevSelectedIconPopover ? null : item.key + ); }} onClose={() => { setSelectedIconPopover(null); diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx index 3f74b80bab064..312513db80886 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx @@ -63,7 +63,13 @@ export function TransactionActionMenu({ transaction }: Props) { isOpen={isActionPopoverOpen} anchorPosition="downRight" button={ - setIsActionPopoverOpen(true)} /> + + setIsActionPopoverOpen( + (prevIsActionPopoverOpen) => !prevIsActionPopoverOpen + ) + } + /> } >
From 1363a2aa73c8f4051041c49cf40950bd08dae36e Mon Sep 17 00:00:00 2001 From: Ryland Herrick Date: Mon, 4 Jan 2021 18:47:08 -0600 Subject: [PATCH 11/32] [Security Solution] Cypress documentation updates (#86835) * Update/refactor some cypress documentation * Fixes some whitespace/grammar/typos * Condenses the explanation/instructions for the different modes of execution * Condense Artifacts section This is a big sprawling file; trying to cut down on the noise. * Move test-running section to top of README This is going to be what 90% of readers are looking for, methinks. * Adds Security Solution's cypress suite to x-pack testing README * Fix broken link This file was moved as part of #64368. * Remove broken link This file was deleted in #67138. * Apply suggestions from code review Co-authored-by: Devin W. Hurley * Fix typo Co-authored-by: Devin W. Hurley --- x-pack/README.md | 7 +- .../security_solution/cypress/README.md | 272 ++++++++---------- 2 files changed, 119 insertions(+), 160 deletions(-) diff --git a/x-pack/README.md b/x-pack/README.md index 41ea4cc4e469a..3f651336f7f3b 100644 --- a/x-pack/README.md +++ b/x-pack/README.md @@ -84,8 +84,9 @@ Jest integration tests can be used to test behavior with Elasticsearch and the K yarn test:jest_integration ``` -An example test exists at [test_utils/jest/integration_tests/example_integration.test.ts](test_utils/jest/integration_tests/example_integration.test.ts) - #### Running Reporting functional tests -See [here](test/reporting/README.md) for more information on running reporting tests. +See [here](./test/functional/apps/dashboard/reporting/README.md) for more information on running reporting tests. + +#### Running Security Solution Cypress E2E/integration tests +See [here](./plugins/security_solution/cypress/README.md) for information on running this test suite. diff --git a/x-pack/plugins/security_solution/cypress/README.md b/x-pack/plugins/security_solution/cypress/README.md index 4fb98f0983ee9..feb11f55590ad 100644 --- a/x-pack/plugins/security_solution/cypress/README.md +++ b/x-pack/plugins/security_solution/cypress/README.md @@ -2,190 +2,177 @@ The `security_solution/cypress` directory contains functional UI tests that execute using [Cypress](https://www.cypress.io/). -## Folder Structure +## Running the tests -### Fixtures (Cypress native folder) +There are currently four ways to run the tests, comprised of two execution modes and two target environments, which will be detailed below. -Fixtures are used as external pieces of static data when we stub responses. +### Execution modes -### Integration (Cypress native folder) +#### Interactive mode -Contains the specs that are going to be executed. +When you run Cypress in interactive mode, an interactive runner is displayed that allows you to see commands as they execute while also viewing the application under test. For more information, please see [cypress documentation](https://docs.cypress.io/guides/core-concepts/test-runner.html#Overview). -### Objects +#### Headless mode -Objects are a representation of data used accross different tests. +A headless browser is a browser simulation program that does not have a user interface. These programs operate like any other browser, but do not display any UI. This is why meanwhile you are executing the tests on this mode you are not going to see the application under test. Just the output of the test is displayed on the terminal once the execution is finished. -### Pluggins (Cypress native folder) +### Target environments -By default Cypress will automatically include the plugins file cypress/plugins/index.js before every single spec file it runs. They do this purely as a convenience mechanism so you don’t have to import this that in every single one of your spec files. +#### FTR (CI) -### Screens +This is the configuration used by CI. It uses the FTR to spawn both a Kibana instance (http://localhost:5620) and an Elasticsearch instance (http://localhost:9220) with a preloaded minimum set of data (see preceding "Test data" section), and then executes cypress against this stack. You can find this configuration in `x-pack/test/security_solution_cypress` -In _screens_ folder we are going to find all the elements we want to interact in our tests. +#### Custom Targets -Each file inside the tasks folder represents a screen of our application. When the screens are complex i.e. Hosts contains multiple tabs, the page is represented by a folder and the different important parts are represented by files. +This configuration runs cypress tests against an arbitrary host. +**WARNING**: When using your own instances you need to take into account that if you already have data on it, the tests may fail, as well as, they can put your instances in an undesired state, since our tests uses es_archive to populate data. -i.e. -- tasks - - hosts - - all_hosts.ts - - authentications.ts - - events.ts - - main.ts - - uncommon_processes.ts - -### Tasks +### Test Execution: Examples -_Tasks_ are functions that my be re-used across tests. +#### FTR + Headless -Each file inside the tasks folder represents a screen of our application. When the screens are complex i.e. Hosts contains multiple tabs, the page is represented by a folder and the different important parts are represented by files. +Since this is how tests are run on CI, this will likely be the configuration you want to reproduce failures locally, etc. -i.e. -- tasks - - hosts - - all_hosts.ts - - authentications.ts - - events.ts - - main.ts - - uncommon_processes.ts - -### URLs - -Represents all the URLs used during the tests execution. - -## Test data +```shell +# bootstrap kibana from the project root +yarn kbn bootstrap -The data the tests need: -- Is generated on the fly using our application APIs (preferred way) -- Is ingested on the ELS instance using es_archive +# build the plugins/assets that cypress will execute against +node scripts/build_kibana_platform_plugins -By default when running the tests on Jenkins mode a base set of data is ingested on the ELS instance: an empty kibana index and a set of auditbeat data (the `empty_kibana` and `auditbeat` archives, respectively). This is usually enough to cover most of the scenarios that we are testing. +# launch the cypress test runner +cd x-pack/plugins/security_solution +yarn cypress:run-as-ci +``` -### How to generate a new archive +#### FTR + Interactive -We are using es_archiver in order to manage the data that our Cypress tests needs. +This is the preferred mode for developing new tests. -1. Setup if possible a clean instance of kibana and elasticsearch (if not, possible please try to clean the data that you are going to generate). -2. With the kibana and elasticsearch instance up and running, create the data that you need for your test. -3. When you are sure that you have all the data you need run the following command from: `x-pack/plugins/security_solution` +```shell +# bootstrap kibana from the project root +yarn kbn bootstrap -```sh -node ../../../scripts/es_archiver save --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.js --es-url http://:@: -``` +# build the plugins/assets that cypress will execute against +node scripts/build_kibana_platform_plugins -Example: -```sh -node ../../../scripts/es_archiver save custom_rules ".kibana",".siem-signal*" --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.js --es-url http://elastic:changeme@localhost:9220 +# launch the cypress test runner +cd x-pack/plugins/security_solution +yarn cypress:open-as-ci ``` -Note that the command is going to create the folder if does not exist in the directory with the imported data. +#### Custom Target + Headless -## Running the tests +This mode may be useful for testing a release, e.g. spin up a build candidate +and point cypress at it to catch regressions. -You can run the tests in interactive or headless mode, emulating the Jenkins pipeline or using your own instances. +```shell +# bootstrap kibana from the project root +yarn kbn bootstrap -### Interactive vs Headless mode +# load auditbeat data needed for test execution (which FTR normally does for us) +cd x-pack/plugins/security_solution +node ../../../scripts/es_archiver load auditbeat --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.js --es-url http(s)://:@ --kibana-url http(s)://:@ -#### Interactive +# launch the cypress test runner with overridden environment variables +cd x-pack/plugins/security_solution +CYPRESS_BASE_URL=http(s)://:@ CYPRESS_ELASTICSEARCH_URL=http(s)://:@ CYPRESS_ELASTICSEARCH_USERNAME= CYPRESS_ELASTICSEARCH_PASSWORD=password yarn cypress:run +``` -When you run the Cypress on interactive mode, an interactive runner is displayed that allows you to see commands as they execute while also viewing the application under test. +## Folder Structure -For more information, please visit: https://docs.cypress.io/guides/core-concepts/test-runner.html#Overview +### integration/ -#### Headless mode +Cypress convention. Contains the specs that are going to be executed. -A headless browser is a browser simulation program that does not have a user interface. These programs operate like any other browser, but do not display any UI. This is why meanwhile you are executing the tests on this mode you are not going to see the application under test. Just the output of the test is displayed on the terminal once the execution is finished. +### fixtures/ -### Emulating Jenkins vs your own instances +Cypress convention. Fixtures are used as external pieces of static data when we stub responses. -#### Emulating Jenkins +### plugins/ -With this mode we use the FTR to run the Cypress tests and automatically, a Kibana instance (http://localhost:5620) and Elastic Search instance (http://localhost:9220) with a preloaded minimum set of data. +Cypress convention. As a convenience, by default Cypress will automatically include the plugins file cypress/plugins/index.js before every single spec file it runs. -You can find the configuration of this mode in `x-pack/test/security_solution_cypress` +### objects/ -#### Your own instances +Contains representations of data used across different tests; our domain objects. -When using your own instances you need to take into account that if you already have data on it, the tests may fail, as well as, they can put your instances in an undesired state, since our tests uses es_archive to populate data. +### screens/ +Contains the elements we want to interact with in our tests. -### Running Cypress in Headless mode as a Jenkins execution (The preferred way when running regressions on your machine) +Each file inside the screens folder represents a screen in our application. When the screens are complex, e.g. Hosts with its multiple tabs, the page is represented by a folder and the different important parts are represented by files. -1. First bootstrap kibana changes from the Kibana root directory: +Example: -```sh -yarn kbn bootstrap -``` +- screens + - hosts + - all_hosts.ts + - authentications.ts + - events.ts + - main.ts + - uncommon_processes.ts -2. Build the plugins +### tasks/ -```sh -node scripts/build_kibana_platform_plugins -``` +_Tasks_ are functions that may be reused across tests. -3. Launch Cypress command line test runner: +Each file inside the tasks folder represents a screen of our application. When the screens are complex, e.g. Hosts with its multiple tabs, the page is represented by a folder and the different important parts are represented by files. -```sh -cd x-pack/plugins/security_solution -yarn cypress:run-as-ci -``` +Example: -As explained previously, this type of execution you don't need to have running a kibana and elasticsearch instance. This is because the command, as it would happen in the CI, will launch the instances. The elasticsearch instance will be fed data found in: `x-pack/test/security_solution_cypress/es_archives` - -### Running Cypress in Interactive mode as a Jenkins execution (The preferred way when developing new cypress tests) +- tasks + - hosts + - all_hosts.ts + - authentications.ts + - events.ts + - main.ts + - uncommon_processes.ts -1. First bootstrap kibana changes from the Kibana root directory: +### urls/ -```sh -yarn kbn bootstrap -``` +Represents all the URLs used during the tests execution. -2. Build the plugins +## Test data -```sh -node scripts/build_kibana_platform_plugins -``` +The data the tests need: -3. Launch Cypress command line test runner: +- Is generated on the fly using our application APIs (preferred way) +- Is ingested on the ELS instance using the `es_archive` utility -```sh -cd x-pack/plugins/security_solution -yarn cypress:open-as-ci -``` +By default, when running the tests in Jenkins mode, a base set of data is ingested on the ELS instance: an empty kibana index and a set of auditbeat data (the `empty_kibana` and `auditbeat` archives, respectively). This is usually enough to cover most of the scenarios that we are testing. -As explained previously, this type of execution you don't need to have running a kibana and elasticsearch instance. This is because the command, as it would happen in the CI, will launch the instances. The elasticsearch instance will be fed data found in: `x-pack/test/security_solution_cypress/es_archives` - -### Running Cypress in your own instances (Recommended just for releases regressions) +### How to generate a new archive -1. First bootstrap kibana changes from the Kibana root directory: +**Note:** As mentioned above, archives are only meant to contain external data, e.g. beats data. Due to the tendency for archived domain objects (rules, signals) to quickly become out of date, it is strongly suggested that you generate this data within the test, through interaction with either the UI or the API. -```sh -yarn kbn bootstrap -``` +We use es_archiver to manage the data that our Cypress tests need. -2. Load the initial auditbeat set of data needed for the test execution: +1. Set up a clean instance of kibana and elasticsearch (if this is not possible, try to clean/minimize the data that you are going to archive). +2. With the kibana and elasticsearch instance up and running, create the data that you need for your test. +3. When you are sure that you have all the data you need run the following command from: `x-pack/plugins/security_solution` ```sh -cd x-pack/plugins/security_solution -node ../../../scripts/es_archiver load auditbeat --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.js --es-url http(s)://:@ --kibana-url http(s)://:@ +node ../../../scripts/es_archiver save --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.js --es-url http://:@: ``` -3. Launch Cypress overriden some of the environment variables: +Example: ```sh -CYPRESS_BASE_URL=http(s)://:@ CYPRESS_ELASTICSEARCH_URL=http(s)://:@ CYPRESS_ELASTICSEARCH_USERNAME= CYPRESS_ELASTICSEARCH_PASSWORD=password yarn cypress:run +node ../../../scripts/es_archiver save custom_rules ".kibana",".siem-signal*" --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.js --es-url http://elastic:changeme@localhost:9220 ``` -## Best Practices +Note that the command will create the folder if it does not exist. + +## Development Best Practices ### Clean up the state -Remember to use the `cleanKibana` method before starting the execution of the test +Remember to clean up the state of the test after its execution, typically with the `cleanKibana` function. Be mindful of failure scenarios, as well: if your test fails, will it leave the environment in a recoverable state? ### Minimize the use of es_archive -When possible, create all the data that you need for executing the tests using the application APIS. +When possible, create all the data that you need for executing the tests using the application APIS or the UI. ### Speed up test execution time @@ -194,54 +181,25 @@ taken into consideration until another solution is implemented: - Group the tests that are similar in different contexts. - For every context login only once, clean the state between tests if needed without re-loading the page. -- All tests in a spec file must be order-independent. - -Remember that minimizing the number of times the web page is loaded, we minimize as well the execution time. - -## Reporting - -When Cypress tests are run on the command line via non visual mode -reporting artifacts are generated under the `target` directory in the root -of the Kibana, as detailed for each artifact type in the sections below. - -### HTML Reports - -An HTML report (e.g. for email notifications) is output to: - -``` -target/kibana-security-solution/cypress/results/output.html -``` +- All tests in a spec file must be order-independent. -### Screenshots - -Screenshots of failed tests are output to: - -``` -target/kibana-security-solution/cypress/screenshots -``` - -### `junit` Reports - -The Kibana CI process reports `junit` test results from the `target/junit` directory. - -Cypress `junit` reports are generated in `target/kibana-security-solution/cypress/results` -and copied to the `target/junit` directory. - -### Videos (optional) +Remember that minimizing the number of times the web page is loaded, we minimize as well the execution time. -Videos are disabled by default, but can optionally be enabled by setting the -`CYPRESS_video=true` environment variable: +## Test Artifacts -``` -CYPRESS_video=true yarn cypress:run -``` +When Cypress tests are run headless on the command line, artifacts +are generated under the `target` directory in the root of Kibana as follows: -Videos are (optionally) output to: - -``` -target/kibana-security-solution/cypress/videos -``` +- HTML Reports + - location: `target/kibana-security-solution/cypress/results/output.html` +- `junit` Reports + - location: `target/kibana-security-solution/cypress/results` +- Screenshots (of failed tests) + - location: `target/kibana-security-solution/cypress/screenshots` +- Videos + - disabled by default, can be enabled by setting env var `CYPRESS_video=true` + - location: `target/kibana-security-solution/cypress/videos` -## Linting +## Linting Optional linting rules for Cypress and linting setup can be found [here](https://github.com/cypress-io/eslint-plugin-cypress#usage) From 0af81310b6c4ce72a628fe08542c9b2f59113cb3 Mon Sep 17 00:00:00 2001 From: Josh Dover Date: Tue, 5 Jan 2021 02:11:05 -0700 Subject: [PATCH 12/32] Remove dynamic mapped types from UiActions (#87075) * Remove dynamic mapped types from UiActions * Remove import between data <-> embeddables * remove outdated comments, export action types from discover_enhanced * fix notice.txt Co-authored-by: restrry --- ...ns-embeddable-public.contextmenutrigger.md | 2 +- ...ble-public.embeddable.supportedtriggers.md | 4 +- ...le-public.iembeddable.supportedtriggers.md | 4 +- ...ins-embeddable-public.panelbadgetrigger.md | 2 +- ...eddable-public.panelnotificationtrigger.md | 2 +- ...plugin-plugins-ui_actions-public.action.md | 4 +- ...n-plugins-ui_actions-public.action.type.md | 2 +- ...-plugins-ui_actions-public.actionbytype.md | 11 -- ..._actions-public.actioncontextmapping.__.md | 11 -- ...oncontextmapping.action_visualize_field.md | 11 -- ...ntextmapping.action_visualize_geo_field.md | 11 -- ...textmapping.action_visualize_lens_field.md | 11 -- ...-ui_actions-public.actioncontextmapping.md | 21 ---- ...i_actions-public.actiondefinitionbytype.md | 11 -- ...i_actions-public.actionexecutioncontext.md | 2 +- ...in-plugins-ui_actions-public.actiontype.md | 11 -- ...-plugins-ui_actions-public.createaction.md | 6 +- ...kibana-plugin-plugins-ui_actions-public.md | 7 -- ...ugins-ui_actions-public.rowclicktrigger.md | 2 +- ...in-plugins-ui_actions-public.trigger.id.md | 2 +- ...lugin-plugins-ui_actions-public.trigger.md | 4 +- ...lugins-ui_actions-public.triggercontext.md | 11 -- ...actions-public.triggercontextmapping.__.md | 11 -- ...ui_actions-public.triggercontextmapping.md | 21 ---- ...triggercontextmapping.row_click_trigger.md | 11 -- ...rcontextmapping.visualize_field_trigger.md | 11 -- ...textmapping.visualize_geo_field_trigger.md | 11 -- ...gin-plugins-ui_actions-public.triggerid.md | 11 -- ...ctions-public.uiactionsactiondefinition.md | 4 +- ...s-public.uiactionsactiondefinition.type.md | 2 +- ...-ui_actions-public.uiactionspresentable.md | 2 +- ...ons-public.uiactionspresentablegrouping.md | 2 +- ...ublic.uiactionsservice.addtriggeraction.md | 2 +- ...ns-public.uiactionsservice.attachaction.md | 2 +- ...ns-public.uiactionsservice.detachaction.md | 2 +- ....uiactionsservice.executetriggeractions.md | 2 +- ...tions-public.uiactionsservice.getaction.md | 2 +- ...ions-public.uiactionsservice.gettrigger.md | 2 +- ...blic.uiactionsservice.gettriggeractions.md | 2 +- ...ionsservice.gettriggercompatibleactions.md | 2 +- ...gins-ui_actions-public.uiactionsservice.md | 18 +-- ...-public.uiactionsservice.registeraction.md | 2 +- ...ui_actions-public.visualizefieldtrigger.md | 2 +- ...actions-public.visualizegeofieldtrigger.md | 2 +- .../book/add_book_to_library_action.tsx | 1 + .../public/book/edit_book_action.tsx | 1 + .../book/unlink_book_from_library_action.tsx | 1 + examples/embeddable_examples/public/plugin.ts | 22 +--- .../public/hello_world_action.tsx | 1 + examples/ui_action_examples/public/plugin.ts | 14 +-- .../public/actions/actions.tsx | 18 ++- examples/ui_actions_explorer/public/app.tsx | 2 +- .../ui_actions_explorer/public/plugin.tsx | 26 ----- .../actions/add_to_library_action.tsx | 4 +- .../actions/clone_panel_action.tsx | 4 +- .../actions/expand_panel_action.tsx | 4 +- .../application/actions/export_csv_action.tsx | 4 +- .../actions/library_notification_action.tsx | 4 +- .../actions/replace_panel_action.tsx | 4 +- .../actions/unlink_from_library_action.tsx | 4 +- src/plugins/dashboard/public/plugin.tsx | 30 +---- .../dashboard/public/services/ui_actions.ts | 2 +- .../public/actions/apply_filter_action.ts | 6 +- .../create_filters_from_range_select.test.ts | 8 +- .../public/actions/select_range_action.ts | 6 +- .../data/public/actions/value_click_action.ts | 6 +- src/plugins/data/public/plugin.ts | 22 +--- .../public/triggers/apply_filter_trigger.ts | 2 +- .../components/data_table.tsx | 6 +- src/plugins/embeddable/public/bootstrap.ts | 31 ------ .../public/lib/embeddables/embeddable.tsx | 3 +- .../public/lib/embeddables/i_embeddable.ts | 3 +- .../lib/panel/embeddable_panel.test.tsx | 6 +- .../test_samples/actions/edit_mode_action.ts | 9 +- .../test_samples/actions/say_hello_action.tsx | 8 +- .../actions/send_message_action.tsx | 9 +- .../embeddables/contact_card/contact_card.tsx | 7 -- .../public/lib/triggers/triggers.ts | 10 +- src/plugins/embeddable/public/public.api.md | 12 +- .../ui_actions/public/actions/action.test.ts | 14 +-- .../ui_actions/public/actions/action.ts | 19 +--- .../public/actions/action_internal.ts | 3 +- .../public/actions/create_action.ts | 19 +--- .../build_eui_context_menu_panels.test.ts | 1 + .../build_eui_context_menu_panels.tsx | 3 +- src/plugins/ui_actions/public/index.ts | 12 +- src/plugins/ui_actions/public/mocks.ts | 3 +- src/plugins/ui_actions/public/public.api.md | 104 ++++-------------- .../service/ui_actions_execution_service.ts | 7 +- .../public/service/ui_actions_service.test.ts | 40 +++---- .../public/service/ui_actions_service.ts | 50 +++------ .../tests/execute_trigger_actions.test.ts | 43 +++----- .../public/tests/get_trigger_actions.test.ts | 17 ++- .../get_trigger_compatible_actions.test.ts | 29 ++--- .../tests/test_samples/hello_world_action.tsx | 14 +-- .../public/triggers/default_trigger.ts | 2 +- .../public/triggers/row_click_trigger.ts | 2 +- .../ui_actions/public/triggers/trigger.ts | 8 +- .../public/triggers/trigger_contract.ts | 9 +- .../public/triggers/trigger_internal.ts | 9 +- .../triggers/visualize_field_trigger.ts | 2 +- .../triggers/visualize_geo_field_trigger.ts | 2 +- src/plugins/ui_actions/public/types.ts | 32 +----- .../ui_actions/public/util/presentable.ts | 6 +- .../public/embeddable/visualize_embeddable.ts | 3 +- .../visualizations/public/vis_types/types.ts | 3 +- .../vis_types/vis_type_alias_registry.ts | 5 +- .../public/actions/visualize_field_action.ts | 2 +- .../public/sample_panel_action.tsx | 9 +- .../public/sample_panel_link.ts | 9 +- .../app1_hello_world_drilldown.tsx | 2 +- .../app1_to_dashboard_drilldown.ts | 5 +- .../app2_to_dashboard_drilldown.ts | 5 +- .../dashboard_hello_world_drilldown/index.tsx | 5 +- .../index.tsx | 4 +- .../drilldown.tsx | 7 +- .../public/triggers/sample_app1_trigger.ts | 8 +- .../public/triggers/sample_app2_trigger.ts | 8 +- .../abstract_dashboard_drilldown.tsx | 21 ++-- .../abstract_dashboard_drilldown/types.ts | 3 +- .../drilldowns/actions/drilldown_shared.ts | 3 +- .../flyout_create_drilldown.test.tsx | 10 +- .../flyout_create_drilldown.tsx | 4 +- .../flyout_edit_drilldown.tsx | 4 +- .../flyout_edit_drilldown/menu_item.test.tsx | 1 + .../flyout_edit_drilldown/menu_item.tsx | 5 +- .../drilldowns/actions/test_helpers.ts | 10 +- .../dashboard_drilldowns_services.ts | 15 +-- ...embeddable_to_dashboard_drilldown.test.tsx | 3 +- .../embeddable_to_dashboard_drilldown.tsx | 10 +- .../plugins/discover_enhanced/public/index.ts | 6 +- .../discover_enhanced/public/plugin.ts | 16 +-- .../public/lib/url_drilldown.tsx | 4 +- .../embeddable_enhanced/public/plugin.ts | 10 +- .../workspace_panel/workspace_panel.test.tsx | 6 +- .../visualize_field_actions.ts | 2 +- x-pack/plugins/lens/public/types.ts | 15 +-- .../maps/public/embeddable/map_embeddable.tsx | 7 +- .../public/trigger_actions/trigger_utils.ts | 1 - .../visualize_geo_field_action.ts | 3 +- .../embeddable_swim_lane_container.test.tsx | 5 +- .../apply_influencer_filters_action.tsx | 10 +- .../ui_actions/apply_time_range_action.tsx | 10 +- .../ui_actions/clear_selection_action.tsx | 10 +- .../ui_actions/edit_swimlane_panel_action.tsx | 10 +- x-pack/plugins/ml/public/ui_actions/index.ts | 41 +------ .../open_in_anomaly_explorer_action.tsx | 10 +- .../plugins/ml/public/ui_actions/triggers.ts | 2 +- .../action_wizard/action_wizard.tsx | 26 ++--- .../components/action_wizard/test_data.tsx | 9 +- .../public/custom_time_range_action.tsx | 7 +- .../public/custom_time_range_badge.tsx | 4 +- .../connected_flyout_manage_drilldowns.tsx | 12 +- .../test_data.ts | 8 +- .../flyout_drilldown_wizard.stories.tsx | 10 +- .../flyout_drilldown_wizard.tsx | 12 +- .../form_drilldown_wizard.stories.tsx | 8 +- .../form_drilldown_wizard.test.tsx | 8 +- .../form_drilldown_wizard.tsx | 8 +- .../public/drilldowns/drilldown_definition.ts | 31 +----- .../hooks/use_drilldown_state_manager.tsx | 5 +- .../public/dynamic_actions/action_factory.ts | 28 ++--- .../action_factory_definition.ts | 13 +-- .../dynamic_actions/dynamic_action_manager.ts | 13 +-- .../public/dynamic_actions/types.ts | 5 +- .../ui_actions_enhanced/public/plugin.ts | 27 +---- .../ui_actions_service_enhancements.ts | 38 ++----- 167 files changed, 483 insertions(+), 1149 deletions(-) delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionbytype.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.__.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_field.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_geo_field.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_lens_field.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiondefinitionbytype.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiontype.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontext.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.row_click_trigger.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md delete mode 100644 docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggerid.md diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.contextmenutrigger.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.contextmenutrigger.md index 0a88e1e0a2ea8..eec1e9ac7e3fb 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.contextmenutrigger.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.contextmenutrigger.md @@ -7,5 +7,5 @@ Signature: ```typescript -contextMenuTrigger: Trigger<'CONTEXT_MENU_TRIGGER'> +contextMenuTrigger: Trigger ``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.supportedtriggers.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.supportedtriggers.md index 16676bc732b1c..8a5efe60ba411 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.supportedtriggers.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.supportedtriggers.md @@ -7,9 +7,9 @@ Signature: ```typescript -supportedTriggers(): Array; +supportedTriggers(): string[]; ``` Returns: -`Array` +`string[]` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.supportedtriggers.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.supportedtriggers.md index 5480f3b246648..bb560c11bf440 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.supportedtriggers.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.supportedtriggers.md @@ -9,9 +9,9 @@ List of triggers that this embeddable will execute. Signature: ```typescript -supportedTriggers(): Array; +supportedTriggers(): string[]; ``` Returns: -`Array` +`string[]` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelbadgetrigger.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelbadgetrigger.md index f6113c93a1c66..feacd0152d384 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelbadgetrigger.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelbadgetrigger.md @@ -7,5 +7,5 @@ Signature: ```typescript -panelBadgeTrigger: Trigger<'PANEL_BADGE_TRIGGER'> +panelBadgeTrigger: Trigger ``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotificationtrigger.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotificationtrigger.md index df606c11f64ce..c831df19d2959 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotificationtrigger.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotificationtrigger.md @@ -7,5 +7,5 @@ Signature: ```typescript -panelNotificationTrigger: Trigger<'PANEL_NOTIFICATION_TRIGGER'> +panelNotificationTrigger: Trigger ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.md index 19af63a679de8..d8e527debcc4e 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.md @@ -7,7 +7,7 @@ Signature: ```typescript -export interface Action extends Partial>> +export interface Action extends Partial>> ``` ## Properties @@ -17,7 +17,7 @@ export interface Action extend | [id](./kibana-plugin-plugins-ui_actions-public.action.id.md) | string | A unique identifier for this action instance. | | [MenuItem](./kibana-plugin-plugins-ui_actions-public.action.menuitem.md) | UiComponent<{
context: ActionExecutionContext<Context>;
}> | UiComponent to render when displaying this action as a context menu item. If not provided, getDisplayName will be used instead. | | [order](./kibana-plugin-plugins-ui_actions-public.action.order.md) | number | Determined the order when there is more than one action matched to a trigger. Higher numbers are displayed first. | -| [type](./kibana-plugin-plugins-ui_actions-public.action.type.md) | T | The action type is what determines the context shape. | +| [type](./kibana-plugin-plugins-ui_actions-public.action.type.md) | string | The action type is what determines the context shape. | ## Methods diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.type.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.type.md index c423df9d1324c..6905f3deb441d 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.type.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.type.md @@ -9,5 +9,5 @@ The action type is what determines the context shape. Signature: ```typescript -readonly type: T; +readonly type: string; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionbytype.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionbytype.md deleted file mode 100644 index 3ceb96adadb1a..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionbytype.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionByType](./kibana-plugin-plugins-ui_actions-public.actionbytype.md) - -## ActionByType type - -Signature: - -```typescript -export declare type ActionByType = Action; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.__.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.__.md deleted file mode 100644 index eb7b1e5954ed2..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.__.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) > [""](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.__.md) - -## ActionContextMapping."" property - -Signature: - -```typescript -[DEFAULT_ACTION]: BaseContext; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_field.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_field.md deleted file mode 100644 index eb0547bbf8261..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_field.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) > [ACTION\_VISUALIZE\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_field.md) - -## ActionContextMapping.ACTION\_VISUALIZE\_FIELD property - -Signature: - -```typescript -[ACTION_VISUALIZE_FIELD]: VisualizeFieldContext; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_geo_field.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_geo_field.md deleted file mode 100644 index b44ed75106423..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_geo_field.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) > [ACTION\_VISUALIZE\_GEO\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_geo_field.md) - -## ActionContextMapping.ACTION\_VISUALIZE\_GEO\_FIELD property - -Signature: - -```typescript -[ACTION_VISUALIZE_GEO_FIELD]: VisualizeFieldContext; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_lens_field.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_lens_field.md deleted file mode 100644 index 96370a07806d3..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_lens_field.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) > [ACTION\_VISUALIZE\_LENS\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_lens_field.md) - -## ActionContextMapping.ACTION\_VISUALIZE\_LENS\_FIELD property - -Signature: - -```typescript -[ACTION_VISUALIZE_LENS_FIELD]: VisualizeFieldContext; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md deleted file mode 100644 index f83632dea0aa9..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md +++ /dev/null @@ -1,21 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) - -## ActionContextMapping interface - -Signature: - -```typescript -export interface ActionContextMapping -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [""](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.__.md) | BaseContext | | -| [ACTION\_VISUALIZE\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_field.md) | VisualizeFieldContext | | -| [ACTION\_VISUALIZE\_GEO\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_geo_field.md) | VisualizeFieldContext | | -| [ACTION\_VISUALIZE\_LENS\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_lens_field.md) | VisualizeFieldContext | | - diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiondefinitionbytype.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiondefinitionbytype.md deleted file mode 100644 index ba4dc39088fe4..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiondefinitionbytype.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionDefinitionByType](./kibana-plugin-plugins-ui_actions-public.actiondefinitionbytype.md) - -## ActionDefinitionByType type - -Signature: - -```typescript -export declare type ActionDefinitionByType = ActionDefinition; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutioncontext.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutioncontext.md index 3271d86779959..d6f754a1ba458 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutioncontext.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutioncontext.md @@ -9,5 +9,5 @@ Action methods are executed with Context from trigger + [ActionExecutionMeta](./ Signature: ```typescript -export declare type ActionExecutionContext = Context & ActionExecutionMeta; +export declare type ActionExecutionContext = Context & ActionExecutionMeta; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiontype.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiontype.md deleted file mode 100644 index 4916585531004..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiontype.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionType](./kibana-plugin-plugins-ui_actions-public.actiontype.md) - -## ActionType type - -Signature: - -```typescript -export declare type ActionType = keyof ActionContextMapping; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.createaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.createaction.md index 04ab36c2e3f58..8bb9094a1d8bf 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.createaction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.createaction.md @@ -7,16 +7,16 @@ Signature: ```typescript -export declare function createAction(action: ActionDefinitionByType): ActionByType; +export declare function createAction(action: ActionDefinition): Action; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| action | ActionDefinitionByType<T> | | +| action | ActionDefinition<Context> | | Returns: -`ActionByType` +`Action` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.md index 76e347bddd168..9f009d1617cc8 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.md @@ -24,11 +24,9 @@ | Interface | Description | | --- | --- | | [Action](./kibana-plugin-plugins-ui_actions-public.action.md) | | -| [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) | | | [ActionExecutionMeta](./kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.md) | During action execution we can provide additional information, for example, trigger, that caused the action execution | | [RowClickContext](./kibana-plugin-plugins-ui_actions-public.rowclickcontext.md) | | | [Trigger](./kibana-plugin-plugins-ui_actions-public.trigger.md) | This is a convenience interface used to register a \*trigger\*.Trigger specifies a named anchor to which Action can be attached. When Trigger is being \*called\* it creates a Context object and passes it to the execute method of an Action.More than one action can be attached to a single trigger, in which case when trigger is \*called\* it first displays a context menu for user to pick a single action to execute. | -| [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) | | | [UiActionsActionDefinition](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md) | A convenience interface used to register an action. | | [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) | Represents something that can be displayed to user in UI. | | [UiActionsServiceParams](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.md) | | @@ -52,12 +50,7 @@ | Type Alias | Description | | --- | --- | -| [ActionByType](./kibana-plugin-plugins-ui_actions-public.actionbytype.md) | | -| [ActionDefinitionByType](./kibana-plugin-plugins-ui_actions-public.actiondefinitionbytype.md) | | | [ActionExecutionContext](./kibana-plugin-plugins-ui_actions-public.actionexecutioncontext.md) | Action methods are executed with Context from trigger + [ActionExecutionMeta](./kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.md) | -| [ActionType](./kibana-plugin-plugins-ui_actions-public.actiontype.md) | | -| [TriggerContext](./kibana-plugin-plugins-ui_actions-public.triggercontext.md) | | -| [TriggerId](./kibana-plugin-plugins-ui_actions-public.triggerid.md) | | | [UiActionsPresentableGrouping](./kibana-plugin-plugins-ui_actions-public.uiactionspresentablegrouping.md) | | | [UiActionsSetup](./kibana-plugin-plugins-ui_actions-public.uiactionssetup.md) | | | [UiActionsStart](./kibana-plugin-plugins-ui_actions-public.uiactionsstart.md) | | diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclicktrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclicktrigger.md index aa1097d8c0864..f05138296e6e8 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclicktrigger.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.rowclicktrigger.md @@ -7,5 +7,5 @@ Signature: ```typescript -rowClickTrigger: Trigger<'ROW_CLICK_TRIGGER'> +rowClickTrigger: Trigger ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.id.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.id.md index 5603c852ad39d..5bf868720cdec 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.id.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.id.md @@ -9,5 +9,5 @@ Unique name of the trigger as identified in `ui_actions` plugin trigger registry Signature: ```typescript -id: ID; +id: string; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.md index ed76cfea97684..d829d7b87c177 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.md @@ -13,7 +13,7 @@ More than one action can be attached to a single trigger, in which case when tri Signature: ```typescript -export interface Trigger +export interface Trigger ``` ## Properties @@ -21,6 +21,6 @@ export interface Trigger | Property | Type | Description | | --- | --- | --- | | [description](./kibana-plugin-plugins-ui_actions-public.trigger.description.md) | string | A longer user friendly description of the trigger. | -| [id](./kibana-plugin-plugins-ui_actions-public.trigger.id.md) | ID | Unique name of the trigger as identified in ui_actions plugin trigger registry. | +| [id](./kibana-plugin-plugins-ui_actions-public.trigger.id.md) | string | Unique name of the trigger as identified in ui_actions plugin trigger registry. | | [title](./kibana-plugin-plugins-ui_actions-public.trigger.title.md) | string | User friendly name of the trigger. | diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontext.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontext.md deleted file mode 100644 index 4ce95d27ecffa..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontext.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContext](./kibana-plugin-plugins-ui_actions-public.triggercontext.md) - -## TriggerContext type - -Signature: - -```typescript -export declare type TriggerContext = T extends TriggerId ? TriggerContextMapping[T] : never; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md deleted file mode 100644 index 17ad926f8ee82..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [""](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md) - -## TriggerContextMapping."" property - -Signature: - -```typescript -[DEFAULT_TRIGGER]: TriggerContext; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md deleted file mode 100644 index da7a7a8bfe645..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md +++ /dev/null @@ -1,21 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) - -## TriggerContextMapping interface - -Signature: - -```typescript -export interface TriggerContextMapping -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [""](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md) | TriggerContext | | -| [ROW\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.row_click_trigger.md) | RowClickContext | | -| [VISUALIZE\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md) | VisualizeFieldContext | | -| [VISUALIZE\_GEO\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md) | VisualizeFieldContext | | - diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.row_click_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.row_click_trigger.md deleted file mode 100644 index cf253df337378..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.row_click_trigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [ROW\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.row_click_trigger.md) - -## TriggerContextMapping.ROW\_CLICK\_TRIGGER property - -Signature: - -```typescript -[ROW_CLICK_TRIGGER]: RowClickContext; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md deleted file mode 100644 index feaaffac8a234..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [VISUALIZE\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md) - -## TriggerContextMapping.VISUALIZE\_FIELD\_TRIGGER property - -Signature: - -```typescript -[VISUALIZE_FIELD_TRIGGER]: VisualizeFieldContext; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md deleted file mode 100644 index 023490a2ae027..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [VISUALIZE\_GEO\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md) - -## TriggerContextMapping.VISUALIZE\_GEO\_FIELD\_TRIGGER property - -Signature: - -```typescript -[VISUALIZE_GEO_FIELD_TRIGGER]: VisualizeFieldContext; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggerid.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggerid.md deleted file mode 100644 index 6e5a234e286f9..0000000000000 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggerid.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerId](./kibana-plugin-plugins-ui_actions-public.triggerid.md) - -## TriggerId type - -Signature: - -```typescript -export declare type TriggerId = keyof TriggerContextMapping; -``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md index 7c873715795e9..a4de28ff4d1af 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md @@ -9,7 +9,7 @@ A convenience interface used to register an action. Signature: ```typescript -export interface ActionDefinition extends Partial>> +export interface ActionDefinition extends Partial>> ``` ## Properties @@ -17,7 +17,7 @@ export interface ActionDefinition extends Part | Property | Type | Description | | --- | --- | --- | | [id](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.id.md) | string | ID of the action that uniquely identifies this action in the actions registry. | -| [type](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.type.md) | ActionType | ID of the factory for this action. Used to construct dynamic actions. | +| [type](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.type.md) | string | ID of the factory for this action. Used to construct dynamic actions. | ## Methods diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.type.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.type.md index 125f834e9036e..c2cc8b41568ce 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.type.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.type.md @@ -9,5 +9,5 @@ ID of the factory for this action. Used to construct dynamic actions. Signature: ```typescript -readonly type?: ActionType; +readonly type?: string; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md index 03fa7fb6e447e..659ea999b9f8e 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md @@ -9,7 +9,7 @@ Represents something that can be displayed to user in UI. Signature: ```typescript -export interface Presentable +export interface Presentable ``` ## Properties diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentablegrouping.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentablegrouping.md index a61ff65e39c69..2fb6c3e187d3d 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentablegrouping.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentablegrouping.md @@ -7,5 +7,5 @@ Signature: ```typescript -export declare type PresentableGrouping = Array>; +export declare type PresentableGrouping = Array>; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md index f29d487d774e0..30272cdcdc7f8 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md @@ -11,5 +11,5 @@ Signature: ```typescript -readonly addTriggerAction: (triggerId: T, action: ActionDefinition | Action) => void; +readonly addTriggerAction: (triggerId: string, action: ActionDefinition) => void; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md index 1ebb30c49c0b3..fd17c76b0ee9f 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly attachAction: (triggerId: T, actionId: string) => void; +readonly attachAction: (triggerId: string, actionId: string) => void; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md index a6ff2489c6f0e..bf9c589e59f60 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly detachAction: (triggerId: TriggerId, actionId: string) => void; +readonly detachAction: (triggerId: string, actionId: string) => void; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md index b20f08520c43d..fb1a1ef14d315 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md @@ -12,5 +12,5 @@ Signature: ```typescript -readonly executeTriggerActions: (triggerId: T, context: TriggerContext) => Promise; +readonly executeTriggerActions: (triggerId: string, context: object) => Promise; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md index 300c46a47c47f..32a4fcf8e6f89 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">; +readonly getAction: >(id: string) => Action>; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md index 95b737a8d6cae..b8f59e943f38e 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly getTrigger: (triggerId: T) => TriggerContract; +readonly getTrigger: (triggerId: string) => TriggerContract; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md index 27c1b1eb48f16..c7c0eac755aec 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly getTriggerActions: (triggerId: T) => Action[]; +readonly getTriggerActions: (triggerId: string) => Action[]; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md index edb7d2d3a1551..9e3e38a6ac43d 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; +readonly getTriggerCompatibleActions: (triggerId: string, context: object) => Promise; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md index 4fe8431770dea..fced0bbc3cde2 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md @@ -21,19 +21,19 @@ export declare class UiActionsService | Property | Modifiers | Type | Description | | --- | --- | --- | --- | | [actions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.actions.md) | | ActionRegistry | | -| [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T, action: ActionDefinition<TriggerContextMapping[T]> | Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">) => void | addTriggerAction is similar to attachAction as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet.addTriggerAction also infers better typing of the action argument. | -| [attachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T, actionId: string) => void | | +| [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) | | (triggerId: string, action: ActionDefinition) => void | addTriggerAction is similar to attachAction as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet.addTriggerAction also infers better typing of the action argument. | +| [attachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md) | | (triggerId: string, actionId: string) => void | | | [clear](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.clear.md) | | () => void | Removes all registered triggers and actions. | -| [detachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md) | | (triggerId: TriggerId, actionId: string) => void | | -| [executeTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T, context: TriggerContext<T>) => Promise<void> | | +| [detachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md) | | (triggerId: string, actionId: string) => void | | +| [executeTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md) | | (triggerId: string, context: object) => Promise<void> | | | [executionService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executionservice.md) | | UiActionsExecutionService | | | [fork](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.fork.md) | | () => UiActionsService | "Fork" a separate instance of UiActionsService that inherits all existing triggers and actions, but going forward all new triggers and actions added to this instance of UiActionsService are only available within this instance. | -| [getAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md) | | <T extends ActionDefinition<{}>>(id: string) => Action<ActionContext<T>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel"> | | -| [getTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T) => TriggerContract<T> | | -| [getTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T) => Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">[] | | -| [getTriggerCompatibleActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md) | | <T extends "" | "ROW_CLICK_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "FILTER_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER">(triggerId: T, context: TriggerContextMapping[T]) => Promise<Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">[]> | | +| [getAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md) | | <T extends ActionDefinition<object>>(id: string) => Action<ActionContext<T>> | | +| [getTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md) | | (triggerId: string) => TriggerContract | | +| [getTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md) | | (triggerId: string) => Action[] | | +| [getTriggerCompatibleActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md) | | (triggerId: string, context: object) => Promise<Action[]> | | | [hasAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.hasaction.md) | | (actionId: string) => boolean | | -| [registerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md) | | <A extends ActionDefinition<{}>>(definition: A) => Action<ActionContext<A>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel"> | | +| [registerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md) | | <A extends ActionDefinition<object>>(definition: A) => Action<ActionContext<A>> | | | [registerTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registertrigger.md) | | (trigger: Trigger) => void | | | [triggers](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggers.md) | | TriggerRegistry | | | [triggerToActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggertoactions.md) | | TriggerToActionsRegistry | | diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md index dee5f75f7c074..75289e8f32351 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">; +readonly registerAction: >(definition: A) => Action>; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldtrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldtrigger.md index 15510bd3eb4a3..eb62d36df84d8 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldtrigger.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldtrigger.md @@ -7,5 +7,5 @@ Signature: ```typescript -visualizeFieldTrigger: Trigger<'VISUALIZE_FIELD_TRIGGER'> +visualizeFieldTrigger: Trigger ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizegeofieldtrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizegeofieldtrigger.md index faec6a69b71f9..c547c33aaccbf 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizegeofieldtrigger.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizegeofieldtrigger.md @@ -7,5 +7,5 @@ Signature: ```typescript -visualizeGeoFieldTrigger: Trigger<'VISUALIZE_GEO_FIELD_TRIGGER'> +visualizeGeoFieldTrigger: Trigger ``` 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 index 4ae3a545df0d0..b36635feb3dcc 100644 --- a/examples/embeddable_examples/public/book/add_book_to_library_action.tsx +++ b/examples/embeddable_examples/public/book/add_book_to_library_action.tsx @@ -35,6 +35,7 @@ export const createAddBookToLibraryAction = () => i18n.translate('embeddableExamples.book.addToLibrary', { defaultMessage: 'Add Book To Library', }), + id: ACTION_ADD_BOOK_TO_LIBRARY, type: ACTION_ADD_BOOK_TO_LIBRARY, order: 100, getIconType: () => 'folderCheck', diff --git a/examples/embeddable_examples/public/book/edit_book_action.tsx b/examples/embeddable_examples/public/book/edit_book_action.tsx index 877e50560000e..6fa5ff15716a6 100644 --- a/examples/embeddable_examples/public/book/edit_book_action.tsx +++ b/examples/embeddable_examples/public/book/edit_book_action.tsx @@ -53,6 +53,7 @@ export const createEditBookAction = (getStartServices: () => Promise i18n.translate('embeddableExamples.book.edit', { defaultMessage: 'Edit Book' }), + id: ACTION_EDIT_BOOK, type: ACTION_EDIT_BOOK, order: 100, getIconType: () => 'documents', diff --git a/examples/embeddable_examples/public/book/unlink_book_from_library_action.tsx b/examples/embeddable_examples/public/book/unlink_book_from_library_action.tsx index ebab2c483c625..54857010a1468 100644 --- a/examples/embeddable_examples/public/book/unlink_book_from_library_action.tsx +++ b/examples/embeddable_examples/public/book/unlink_book_from_library_action.tsx @@ -35,6 +35,7 @@ export const createUnlinkBookFromLibraryAction = () => i18n.translate('embeddableExamples.book.unlinkFromLibrary', { defaultMessage: 'Unlink Book from Library Item', }), + id: ACTION_UNLINK_BOOK_FROM_LIBRARY, type: ACTION_UNLINK_BOOK_FROM_LIBRARY, order: 100, getIconType: () => 'folderExclamation', diff --git a/examples/embeddable_examples/public/plugin.ts b/examples/embeddable_examples/public/plugin.ts index 9b9770e40611e..8e8f2ddfe2128 100644 --- a/examples/embeddable_examples/public/plugin.ts +++ b/examples/embeddable_examples/public/plugin.ts @@ -51,21 +51,15 @@ import { TodoRefEmbeddableFactory, TodoRefEmbeddableFactoryDefinition, } from './todo/todo_ref_embeddable_factory'; -import { ACTION_EDIT_BOOK, createEditBookAction } from './book/edit_book_action'; -import { BookEmbeddable, BOOK_EMBEDDABLE } from './book/book_embeddable'; +import { createEditBookAction } from './book/edit_book_action'; +import { BOOK_EMBEDDABLE } from './book/book_embeddable'; import { BookEmbeddableFactory, BookEmbeddableFactoryDefinition, } from './book/book_embeddable_factory'; import { UiActionsStart } from '../../../src/plugins/ui_actions/public'; -import { - ACTION_ADD_BOOK_TO_LIBRARY, - createAddBookToLibraryAction, -} from './book/add_book_to_library_action'; -import { - ACTION_UNLINK_BOOK_FROM_LIBRARY, - createUnlinkBookFromLibraryAction, -} from './book/unlink_book_from_library_action'; +import { createAddBookToLibraryAction } from './book/add_book_to_library_action'; +import { createUnlinkBookFromLibraryAction } from './book/unlink_book_from_library_action'; export interface EmbeddableExamplesSetupDependencies { embeddable: EmbeddableSetup; @@ -92,14 +86,6 @@ export interface EmbeddableExamplesStart { factories: ExampleEmbeddableFactories; } -declare module '../../../src/plugins/ui_actions/public' { - export interface ActionContextMapping { - [ACTION_EDIT_BOOK]: { embeddable: BookEmbeddable }; - [ACTION_ADD_BOOK_TO_LIBRARY]: { embeddable: BookEmbeddable }; - [ACTION_UNLINK_BOOK_FROM_LIBRARY]: { embeddable: BookEmbeddable }; - } -} - export class EmbeddableExamplesPlugin implements Plugin< diff --git a/examples/ui_action_examples/public/hello_world_action.tsx b/examples/ui_action_examples/public/hello_world_action.tsx index da20f40464516..54e3fbe10095c 100644 --- a/examples/ui_action_examples/public/hello_world_action.tsx +++ b/examples/ui_action_examples/public/hello_world_action.tsx @@ -30,6 +30,7 @@ interface StartServices { export const createHelloWorldAction = (getStartServices: () => Promise) => createAction({ + id: ACTION_HELLO_WORLD, type: ACTION_HELLO_WORLD, getDisplayName: () => 'Hello World!', execute: async () => { diff --git a/examples/ui_action_examples/public/plugin.ts b/examples/ui_action_examples/public/plugin.ts index 3a9f673261e33..1d896d3305661 100644 --- a/examples/ui_action_examples/public/plugin.ts +++ b/examples/ui_action_examples/public/plugin.ts @@ -19,8 +19,8 @@ import { Plugin, CoreSetup, CoreStart } from '../../../src/core/public'; import { UiActionsSetup, UiActionsStart } from '../../../src/plugins/ui_actions/public'; -import { createHelloWorldAction, ACTION_HELLO_WORLD } from './hello_world_action'; -import { helloWorldTrigger, HELLO_WORLD_TRIGGER_ID } from './hello_world_trigger'; +import { createHelloWorldAction } from './hello_world_action'; +import { helloWorldTrigger } from './hello_world_trigger'; export interface UiActionExamplesSetupDependencies { uiActions: UiActionsSetup; @@ -30,16 +30,6 @@ export interface UiActionExamplesStartDependencies { uiActions: UiActionsStart; } -declare module '../../../src/plugins/ui_actions/public' { - export interface TriggerContextMapping { - [HELLO_WORLD_TRIGGER_ID]: {}; - } - - export interface ActionContextMapping { - [ACTION_HELLO_WORLD]: {}; - } -} - export class UiActionExamplesPlugin implements Plugin { diff --git a/examples/ui_actions_explorer/public/actions/actions.tsx b/examples/ui_actions_explorer/public/actions/actions.tsx index 777bcd9c18119..1d9987ad73a26 100644 --- a/examples/ui_actions_explorer/public/actions/actions.tsx +++ b/examples/ui_actions_explorer/public/actions/actions.tsx @@ -38,7 +38,8 @@ export const ACTION_EDIT_USER = 'ACTION_EDIT_USER'; export const ACTION_TRIGGER_PHONE_USER = 'ACTION_TRIGGER_PHONE_USER'; export const ACTION_SHOWCASE_PLUGGABILITY = 'ACTION_SHOWCASE_PLUGGABILITY'; -export const showcasePluggability = createAction({ +export const showcasePluggability = createAction({ + id: ACTION_SHOWCASE_PLUGGABILITY, type: ACTION_SHOWCASE_PLUGGABILITY, getDisplayName: () => 'This is pluggable! Any plugin can inject their actions here.', execute: async (context: ActionExecutionContext) => @@ -49,13 +50,15 @@ export interface PhoneContext { phone: string; } -export const makePhoneCallAction = createAction({ +export const makePhoneCallAction = createAction({ + id: ACTION_CALL_PHONE_NUMBER, type: ACTION_CALL_PHONE_NUMBER, getDisplayName: () => 'Call phone number', execute: async (context) => alert(`Pretend calling ${context.phone}...`), }); -export const lookUpWeatherAction = createAction({ +export const lookUpWeatherAction = createAction({ + id: ACTION_TRAVEL_GUIDE, type: ACTION_TRAVEL_GUIDE, getIconType: () => 'popout', getDisplayName: () => 'View travel guide', @@ -68,7 +71,8 @@ export interface CountryContext { country: string; } -export const viewInMapsAction = createAction({ +export const viewInMapsAction = createAction({ + id: ACTION_VIEW_IN_MAPS, type: ACTION_VIEW_IN_MAPS, getIconType: () => 'popout', getDisplayName: () => 'View in maps', @@ -109,7 +113,8 @@ function EditUserModal({ } export const createEditUserAction = (getOpenModal: () => Promise) => - createAction({ + createAction({ + id: ACTION_EDIT_USER, type: ACTION_EDIT_USER, getIconType: () => 'pencil', getDisplayName: () => 'Edit user', @@ -126,7 +131,8 @@ export interface UserContext { } export const createTriggerPhoneTriggerAction = (getUiActionsApi: () => Promise) => - createAction({ + createAction({ + id: ACTION_TRIGGER_PHONE_USER, type: ACTION_TRIGGER_PHONE_USER, getDisplayName: () => 'Call phone number', shouldAutoExecute: async () => true, diff --git a/examples/ui_actions_explorer/public/app.tsx b/examples/ui_actions_explorer/public/app.tsx index bc8bdee75047d..38fc4e22b284f 100644 --- a/examples/ui_actions_explorer/public/app.tsx +++ b/examples/ui_actions_explorer/public/app.tsx @@ -77,7 +77,7 @@ const ActionsExplorer = ({ uiActionsApi, openModal }: Props) => { { - const dynamicAction = createAction({ + const dynamicAction = createAction({ id: `${ACTION_HELLO_WORLD}-${name}`, type: ACTION_HELLO_WORLD, getDisplayName: () => `Say hello to ${name}`, diff --git a/examples/ui_actions_explorer/public/plugin.tsx b/examples/ui_actions_explorer/public/plugin.tsx index b28e5e7a9f692..757a2f1dfa865 100644 --- a/examples/ui_actions_explorer/public/plugin.tsx +++ b/examples/ui_actions_explorer/public/plugin.tsx @@ -28,15 +28,6 @@ import { createEditUserAction, makePhoneCallAction, showcasePluggability, - UserContext, - CountryContext, - PhoneContext, - ACTION_EDIT_USER, - ACTION_SHOWCASE_PLUGGABILITY, - ACTION_CALL_PHONE_NUMBER, - ACTION_TRAVEL_GUIDE, - ACTION_VIEW_IN_MAPS, - ACTION_TRIGGER_PHONE_USER, createTriggerPhoneTriggerAction, } from './actions/actions'; import { DeveloperExamplesSetup } from '../../developer_examples/public'; @@ -51,23 +42,6 @@ interface SetupDeps { developerExamples: DeveloperExamplesSetup; } -declare module '../../../src/plugins/ui_actions/public' { - export interface TriggerContextMapping { - [USER_TRIGGER]: UserContext; - [COUNTRY_TRIGGER]: CountryContext; - [PHONE_TRIGGER]: PhoneContext; - } - - export interface ActionContextMapping { - [ACTION_EDIT_USER]: UserContext; - [ACTION_SHOWCASE_PLUGGABILITY]: {}; - [ACTION_CALL_PHONE_NUMBER]: PhoneContext; - [ACTION_TRAVEL_GUIDE]: CountryContext; - [ACTION_VIEW_IN_MAPS]: CountryContext; - [ACTION_TRIGGER_PHONE_USER]: UserContext; - } -} - export class UiActionsExplorerPlugin implements Plugin { public setup(core: CoreSetup, deps: SetupDeps) { deps.uiActions.registerTrigger({ diff --git a/src/plugins/dashboard/public/application/actions/add_to_library_action.tsx b/src/plugins/dashboard/public/application/actions/add_to_library_action.tsx index 880d40cc3c612..e0d59ef2a17b6 100644 --- a/src/plugins/dashboard/public/application/actions/add_to_library_action.tsx +++ b/src/plugins/dashboard/public/application/actions/add_to_library_action.tsx @@ -19,7 +19,7 @@ import _ from 'lodash'; -import { ActionByType, IncompatibleActionError } from '../../services/ui_actions'; +import { Action, IncompatibleActionError } from '../../services/ui_actions'; import { ViewMode, PanelState, @@ -39,7 +39,7 @@ export interface AddToLibraryActionContext { embeddable: IEmbeddable; } -export class AddToLibraryAction implements ActionByType { +export class AddToLibraryAction implements Action { public readonly type = ACTION_ADD_TO_LIBRARY; public readonly id = ACTION_ADD_TO_LIBRARY; public order = 15; diff --git a/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx b/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx index d27e2d6dce651..e59cefed598e8 100644 --- a/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx +++ b/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx @@ -21,7 +21,7 @@ import _ from 'lodash'; import uuid from 'uuid'; import { CoreStart } from 'src/core/public'; -import { ActionByType, IncompatibleActionError } from '../../services/ui_actions'; +import { Action, IncompatibleActionError } from '../../services/ui_actions'; import { SavedObject } from '../../services/saved_objects'; import { ViewMode, @@ -45,7 +45,7 @@ export interface ClonePanelActionContext { embeddable: IEmbeddable; } -export class ClonePanelAction implements ActionByType { +export class ClonePanelAction implements Action { public readonly type = ACTION_CLONE_PANEL; public readonly id = ACTION_CLONE_PANEL; public order = 45; diff --git a/src/plugins/dashboard/public/application/actions/expand_panel_action.tsx b/src/plugins/dashboard/public/application/actions/expand_panel_action.tsx index fe14ce13d44bc..3336f8dc5915c 100644 --- a/src/plugins/dashboard/public/application/actions/expand_panel_action.tsx +++ b/src/plugins/dashboard/public/application/actions/expand_panel_action.tsx @@ -19,7 +19,7 @@ import { dashboardExpandPanelAction } from '../../dashboard_strings'; import { IEmbeddable } from '../../services/embeddable'; -import { ActionByType, IncompatibleActionError } from '../../services/ui_actions'; +import { Action, IncompatibleActionError } from '../../services/ui_actions'; import { DASHBOARD_CONTAINER_TYPE, DashboardContainer, @@ -46,7 +46,7 @@ export interface ExpandPanelActionContext { embeddable: IEmbeddable; } -export class ExpandPanelAction implements ActionByType { +export class ExpandPanelAction implements Action { public readonly type = ACTION_EXPAND_PANEL; public readonly id = ACTION_EXPAND_PANEL; public order = 7; diff --git a/src/plugins/dashboard/public/application/actions/export_csv_action.tsx b/src/plugins/dashboard/public/application/actions/export_csv_action.tsx index a31ecbea88bab..1048ce2189744 100644 --- a/src/plugins/dashboard/public/application/actions/export_csv_action.tsx +++ b/src/plugins/dashboard/public/application/actions/export_csv_action.tsx @@ -24,7 +24,7 @@ import { FormatFactory } from '../../../../data/common/field_formats/utils'; import { DataPublicPluginStart, exporters } from '../../services/data'; import { downloadMultipleAs } from '../../services/share'; import { Adapters, IEmbeddable } from '../../services/embeddable'; -import { ActionByType } from '../../services/ui_actions'; +import { Action } from '../../services/ui_actions'; import { dashboardExportCsvAction } from '../../dashboard_strings'; export const ACTION_EXPORT_CSV = 'ACTION_EXPORT_CSV'; @@ -44,7 +44,7 @@ export interface ExportContext { * This is "Export CSV" action which appears in the context * menu of a dashboard panel. */ -export class ExportCSVAction implements ActionByType { +export class ExportCSVAction implements Action { public readonly id = ACTION_EXPORT_CSV; public readonly type = ACTION_EXPORT_CSV; diff --git a/src/plugins/dashboard/public/application/actions/library_notification_action.tsx b/src/plugins/dashboard/public/application/actions/library_notification_action.tsx index 13ccb279df821..a6d718846b9fe 100644 --- a/src/plugins/dashboard/public/application/actions/library_notification_action.tsx +++ b/src/plugins/dashboard/public/application/actions/library_notification_action.tsx @@ -19,7 +19,7 @@ import React from 'react'; -import { ActionByType, IncompatibleActionError } from '../../services/ui_actions'; +import { Action, IncompatibleActionError } from '../../services/ui_actions'; import { reactToUiComponent } from '../../services/kibana_react'; import { IEmbeddable, @@ -38,7 +38,7 @@ export interface LibraryNotificationActionContext { embeddable: IEmbeddable; } -export class LibraryNotificationAction implements ActionByType { +export class LibraryNotificationAction implements Action { public readonly id = ACTION_LIBRARY_NOTIFICATION; public readonly type = ACTION_LIBRARY_NOTIFICATION; public readonly order = 1; diff --git a/src/plugins/dashboard/public/application/actions/replace_panel_action.tsx b/src/plugins/dashboard/public/application/actions/replace_panel_action.tsx index 553a0b9770d01..909b758c511a9 100644 --- a/src/plugins/dashboard/public/application/actions/replace_panel_action.tsx +++ b/src/plugins/dashboard/public/application/actions/replace_panel_action.tsx @@ -20,7 +20,7 @@ import { CoreStart } from 'src/core/public'; import { IEmbeddable, ViewMode, EmbeddableStart } from '../../services/embeddable'; import { DASHBOARD_CONTAINER_TYPE, DashboardContainer } from '../embeddable'; -import { ActionByType, IncompatibleActionError } from '../../services/ui_actions'; +import { Action, IncompatibleActionError } from '../../services/ui_actions'; import { openReplacePanelFlyout } from './open_replace_panel_flyout'; import { dashboardReplacePanelAction } from '../../dashboard_strings'; @@ -34,7 +34,7 @@ export interface ReplacePanelActionContext { embeddable: IEmbeddable; } -export class ReplacePanelAction implements ActionByType { +export class ReplacePanelAction implements Action { public readonly type = ACTION_REPLACE_PANEL; public readonly id = ACTION_REPLACE_PANEL; public order = 3; diff --git a/src/plugins/dashboard/public/application/actions/unlink_from_library_action.tsx b/src/plugins/dashboard/public/application/actions/unlink_from_library_action.tsx index 93ceb72624259..901367b6af833 100644 --- a/src/plugins/dashboard/public/application/actions/unlink_from_library_action.tsx +++ b/src/plugins/dashboard/public/application/actions/unlink_from_library_action.tsx @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import { ActionByType, IncompatibleActionError } from '../../services/ui_actions'; +import { Action, IncompatibleActionError } from '../../services/ui_actions'; import { ViewMode, PanelState, @@ -38,7 +38,7 @@ export interface UnlinkFromLibraryActionContext { embeddable: IEmbeddable; } -export class UnlinkFromLibraryAction implements ActionByType { +export class UnlinkFromLibraryAction implements Action { public readonly type = ACTION_UNLINK_FROM_LIBRARY; public readonly id = ACTION_UNLINK_FROM_LIBRARY; public order = 15; diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 4dff423098c5a..166f4eaf39997 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -62,27 +62,15 @@ import { } from './services/kibana_react'; import { - ACTION_CLONE_PANEL, - ACTION_EXPAND_PANEL, - ACTION_REPLACE_PANEL, ClonePanelAction, - ClonePanelActionContext, createDashboardContainerByValueRenderer, DASHBOARD_CONTAINER_TYPE, DashboardContainerFactory, DashboardContainerFactoryDefinition, ExpandPanelAction, - ExpandPanelActionContext, ReplacePanelAction, - ReplacePanelActionContext, - ACTION_UNLINK_FROM_LIBRARY, - UnlinkFromLibraryActionContext, UnlinkFromLibraryAction, - ACTION_ADD_TO_LIBRARY, - AddToLibraryActionContext, AddToLibraryAction, - ACTION_LIBRARY_NOTIFICATION, - LibraryNotificationActionContext, LibraryNotificationAction, } from './application'; import { @@ -94,11 +82,7 @@ import { createSavedDashboardLoader } from './saved_dashboards'; import { DashboardConstants } from './dashboard_constants'; import { PlaceholderEmbeddableFactory } from './application/embeddable/placeholder'; import { UrlGeneratorState } from '../../share/public'; -import { - ACTION_EXPORT_CSV, - ExportContext, - ExportCSVAction, -} from './application/actions/export_csv_action'; +import { ExportCSVAction } from './application/actions/export_csv_action'; import { dashboardFeatureCatalog } from './dashboard_strings'; declare module '../../share/public' { @@ -147,18 +131,6 @@ export interface DashboardStart { DashboardContainerByValueRenderer: ReturnType; } -declare module '../../../plugins/ui_actions/public' { - export interface ActionContextMapping { - [ACTION_EXPAND_PANEL]: ExpandPanelActionContext; - [ACTION_REPLACE_PANEL]: ReplacePanelActionContext; - [ACTION_CLONE_PANEL]: ClonePanelActionContext; - [ACTION_ADD_TO_LIBRARY]: AddToLibraryActionContext; - [ACTION_UNLINK_FROM_LIBRARY]: UnlinkFromLibraryActionContext; - [ACTION_LIBRARY_NOTIFICATION]: LibraryNotificationActionContext; - [ACTION_EXPORT_CSV]: ExportContext; - } -} - export class DashboardPlugin implements Plugin { diff --git a/src/plugins/dashboard/public/services/ui_actions.ts b/src/plugins/dashboard/public/services/ui_actions.ts index 4c9ac590191f6..81bdad35d464c 100644 --- a/src/plugins/dashboard/public/services/ui_actions.ts +++ b/src/plugins/dashboard/public/services/ui_actions.ts @@ -18,7 +18,7 @@ */ export { - ActionByType, + Action, IncompatibleActionError, UiActionsSetup, UiActionsStart, diff --git a/src/plugins/data/public/actions/apply_filter_action.ts b/src/plugins/data/public/actions/apply_filter_action.ts index 84ce5b0382624..909d6e97c221c 100644 --- a/src/plugins/data/public/actions/apply_filter_action.ts +++ b/src/plugins/data/public/actions/apply_filter_action.ts @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; import { toMountPoint } from '../../../kibana_react/public'; -import { ActionByType, createAction, IncompatibleActionError } from '../../../ui_actions/public'; +import { Action, createAction, IncompatibleActionError } from '../../../ui_actions/public'; import { getOverlays, getIndexPatterns } from '../services'; import { applyFiltersPopover } from '../ui/apply_filters'; import { Filter, FilterManager, TimefilterContract, esFilters } from '..'; @@ -41,8 +41,8 @@ async function isCompatible(context: ApplyGlobalFilterActionContext) { export function createFilterAction( filterManager: FilterManager, timeFilter: TimefilterContract -): ActionByType { - return createAction({ +): Action { + return createAction({ type: ACTION_GLOBAL_APPLY_FILTER, id: ACTION_GLOBAL_APPLY_FILTER, order: 100, diff --git a/src/plugins/data/public/actions/filters/create_filters_from_range_select.test.ts b/src/plugins/data/public/actions/filters/create_filters_from_range_select.test.ts index 6dcfa4d02bcb2..9830bf5b7ba83 100644 --- a/src/plugins/data/public/actions/filters/create_filters_from_range_select.test.ts +++ b/src/plugins/data/public/actions/filters/create_filters_from_range_select.test.ts @@ -29,12 +29,16 @@ import { } from '../../../public'; import { dataPluginMock } from '../../../public/mocks'; import { setIndexPatterns, setSearchService } from '../../../public/services'; -import { TriggerContextMapping } from '../../../../ui_actions/public'; describe('brushEvent', () => { const DAY_IN_MS = 24 * 60 * 60 * 1000; const JAN_01_2014 = 1388559600000; - let baseEvent: TriggerContextMapping['SELECT_RANGE_TRIGGER']['data']; + let baseEvent: { + table: any; + column: number; + range: number[]; + timeFieldName?: string; + }; const mockField = { name: 'time', diff --git a/src/plugins/data/public/actions/select_range_action.ts b/src/plugins/data/public/actions/select_range_action.ts index 3b84523d782f6..c6d234665c05e 100644 --- a/src/plugins/data/public/actions/select_range_action.ts +++ b/src/plugins/data/public/actions/select_range_action.ts @@ -18,7 +18,7 @@ */ import { Datatable } from 'src/plugins/expressions/public'; -import { ActionByType, createAction, UiActionsStart } from '../../../../plugins/ui_actions/public'; +import { Action, createAction, UiActionsStart } from '../../../../plugins/ui_actions/public'; import { APPLY_FILTER_TRIGGER } from '../triggers'; import { createFiltersFromRangeSelectAction } from './filters/create_filters_from_range_select'; @@ -38,8 +38,8 @@ export const ACTION_SELECT_RANGE = 'ACTION_SELECT_RANGE'; export function createSelectRangeAction( getStartServices: () => { uiActions: UiActionsStart } -): ActionByType { - return createAction({ +): Action { + return createAction({ type: ACTION_SELECT_RANGE, id: ACTION_SELECT_RANGE, shouldAutoExecute: async () => true, diff --git a/src/plugins/data/public/actions/value_click_action.ts b/src/plugins/data/public/actions/value_click_action.ts index 8f207e94e8fbe..41c2943a6a5bb 100644 --- a/src/plugins/data/public/actions/value_click_action.ts +++ b/src/plugins/data/public/actions/value_click_action.ts @@ -18,7 +18,7 @@ */ import { Datatable } from 'src/plugins/expressions/public'; -import { ActionByType, createAction, UiActionsStart } from '../../../../plugins/ui_actions/public'; +import { Action, createAction, UiActionsStart } from '../../../../plugins/ui_actions/public'; import { APPLY_FILTER_TRIGGER } from '../triggers'; import { createFiltersFromValueClickAction } from './filters/create_filters_from_value_click'; import type { Filter } from '../../common/es_query/filters'; @@ -44,8 +44,8 @@ export interface ValueClickContext { export function createValueClickAction( getStartServices: () => { uiActions: UiActionsStart } -): ActionByType { - return createAction({ +): Action { + return createAction({ type: ACTION_VALUE_CLICK, id: ACTION_VALUE_CLICK, shouldAutoExecute: async () => true, diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index c60a1efabf987..43abe84950fdb 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -53,11 +53,6 @@ import { createFilterAction, createFiltersFromValueClickAction, createFiltersFromRangeSelectAction, - ApplyGlobalFilterActionContext, - ACTION_SELECT_RANGE, - ACTION_VALUE_CLICK, - SelectRangeActionContext, - ValueClickActionContext, createValueClickAction, createSelectRangeAction, } from './actions'; @@ -66,19 +61,6 @@ import { SavedObjectsClientPublicToCommon } from './index_patterns'; import { getIndexPatternLoad } from './index_patterns/expressions'; import { UsageCollectionSetup } from '../../usage_collection/public'; import { getTableViewDescription } from './utils/table_inspector_view'; -import { TriggerId } from '../../ui_actions/public'; - -declare module '../../ui_actions/public' { - export interface TriggerContextMapping { - [APPLY_FILTER_TRIGGER]: ApplyGlobalFilterActionContext; - } - - export interface ActionContextMapping { - [ACTION_GLOBAL_APPLY_FILTER]: ApplyGlobalFilterActionContext; - [ACTION_SELECT_RANGE]: SelectRangeActionContext; - [ACTION_VALUE_CLICK]: ValueClickActionContext; - } -} export class DataPublicPlugin implements @@ -125,14 +107,14 @@ export class DataPublicPlugin ); uiActions.addTriggerAction( - 'SELECT_RANGE_TRIGGER' as TriggerId, + 'SELECT_RANGE_TRIGGER', createSelectRangeAction(() => ({ uiActions: startServices().plugins.uiActions, })) ); uiActions.addTriggerAction( - 'VALUE_CLICK_TRIGGER' as TriggerId, + 'VALUE_CLICK_TRIGGER', createValueClickAction(() => ({ uiActions: startServices().plugins.uiActions, })) diff --git a/src/plugins/data/public/triggers/apply_filter_trigger.ts b/src/plugins/data/public/triggers/apply_filter_trigger.ts index 816c1737608da..07422eb313ae3 100644 --- a/src/plugins/data/public/triggers/apply_filter_trigger.ts +++ b/src/plugins/data/public/triggers/apply_filter_trigger.ts @@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n'; import { Trigger } from '../../../ui_actions/public'; export const APPLY_FILTER_TRIGGER = 'FILTER_TRIGGER'; -export const applyFilterTrigger: Trigger<'FILTER_TRIGGER'> = { +export const applyFilterTrigger: Trigger = { id: APPLY_FILTER_TRIGGER, title: i18n.translate('data.triggers.applyFilterTitle', { defaultMessage: 'Apply filter', diff --git a/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx b/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx index f842568859fc2..f4d1a8988da78 100644 --- a/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx +++ b/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx @@ -38,7 +38,7 @@ import { DataViewRow, DataViewColumn } from '../types'; import { IUiSettingsClient } from '../../../../../../core/public'; import { Datatable, DatatableColumn } from '../../../../../expressions/public'; import { FieldFormatsStart } from '../../../field_formats'; -import { TriggerId, UiActionsStart } from '../../../../../ui_actions/public'; +import { UiActionsStart } from '../../../../../ui_actions/public'; interface DataTableFormatState { columns: DataViewColumn[]; @@ -112,7 +112,7 @@ export class DataTableFormat extends Component { const value = table.rows[rowIndex][column.id]; const eventData = { table, column: columnIndex, row: rowIndex, value }; - uiActions.executeTriggerActions('VALUE_CLICK_TRIGGER' as TriggerId, { + uiActions.executeTriggerActions('VALUE_CLICK_TRIGGER', { data: { data: [eventData] }, }); }} @@ -145,7 +145,7 @@ export class DataTableFormat extends Component { const value = table.rows[rowIndex][column.id]; const eventData = { table, column: columnIndex, row: rowIndex, value }; - uiActions.executeTriggerActions('VALUE_CLICK_TRIGGER' as TriggerId, { + uiActions.executeTriggerActions('VALUE_CLICK_TRIGGER', { data: { data: [eventData], negate: true }, }); }} diff --git a/src/plugins/embeddable/public/bootstrap.ts b/src/plugins/embeddable/public/bootstrap.ts index efaff42c19e2f..7898fac16fd9e 100644 --- a/src/plugins/embeddable/public/bootstrap.ts +++ b/src/plugins/embeddable/public/bootstrap.ts @@ -18,44 +18,13 @@ */ import { UiActionsSetup } from '../../ui_actions/public'; import { - ACTION_ADD_PANEL, - ACTION_CUSTOMIZE_PANEL, - ACTION_EDIT_PANEL, - ACTION_INSPECT_PANEL, - CONTEXT_MENU_TRIGGER, contextMenuTrigger, - EmbeddableContext, - PANEL_BADGE_TRIGGER, - PANEL_NOTIFICATION_TRIGGER, panelBadgeTrigger, panelNotificationTrigger, - RangeSelectContext, - REMOVE_PANEL_ACTION, - SELECT_RANGE_TRIGGER, selectRangeTrigger, - ValueClickContext, - VALUE_CLICK_TRIGGER, valueClickTrigger, } from './lib'; -declare module '../../ui_actions/public' { - export interface TriggerContextMapping { - [CONTEXT_MENU_TRIGGER]: EmbeddableContext; - [PANEL_BADGE_TRIGGER]: EmbeddableContext; - [PANEL_NOTIFICATION_TRIGGER]: EmbeddableContext; - [SELECT_RANGE_TRIGGER]: RangeSelectContext; - [VALUE_CLICK_TRIGGER]: ValueClickContext; - } - - export interface ActionContextMapping { - [ACTION_CUSTOMIZE_PANEL]: EmbeddableContext; - [ACTION_ADD_PANEL]: EmbeddableContext; - [ACTION_INSPECT_PANEL]: EmbeddableContext; - [REMOVE_PANEL_ACTION]: EmbeddableContext; - [ACTION_EDIT_PANEL]: EmbeddableContext; - } -} - /** * This method initializes Embeddable plugin with initial set of * triggers and actions. diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx index 2173082d67d3e..f776e41a20458 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx @@ -25,7 +25,6 @@ import { RenderCompleteDispatcher } from '../../../../kibana_utils/public'; import { Adapters } from '../types'; import { IContainer } from '../containers'; import { EmbeddableOutput, IEmbeddable } from './i_embeddable'; -import { TriggerContextMapping } from '../ui_actions'; import { EmbeddableInput, ViewMode } from '../../../common/types'; function getPanelTitle(input: EmbeddableInput, output: EmbeddableOutput) { @@ -248,7 +247,7 @@ export abstract class Embeddable< this.onResetInput(newInput); } - public supportedTriggers(): Array { + public supportedTriggers(): string[] { return []; } } diff --git a/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts b/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts index a19ec2345db8d..3b0c60f3fb08e 100644 --- a/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts +++ b/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts @@ -20,7 +20,6 @@ import { Observable } from 'rxjs'; import { Adapters } from '../types'; import { IContainer } from '../containers/i_container'; -import { TriggerContextMapping } from '../../../../ui_actions/public'; import { EmbeddableInput } from '../../../common/types'; export interface EmbeddableError { @@ -173,5 +172,5 @@ export interface IEmbeddable< /** * List of triggers that this embeddable will execute. */ - supportedTriggers(): Array; + supportedTriggers(): string[]; } diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx index 2104d93da9ad8..80238b06ff9fa 100644 --- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx +++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx @@ -24,7 +24,7 @@ import { mountWithIntl, nextTick } from '@kbn/test/jest'; import { findTestSubject } from '@elastic/eui/lib/test'; import { I18nProvider } from '@kbn/i18n/react'; import { CONTEXT_MENU_TRIGGER } from '../triggers'; -import { Action, UiActionsStart, ActionType } from '../../../../ui_actions/public'; +import { Action, UiActionsStart } from '../../../../ui_actions/public'; import { Trigger, ViewMode } from '../types'; import { isErrorEmbeddable } from '../embeddables'; import { EmbeddablePanel } from './embeddable_panel'; @@ -216,7 +216,7 @@ const renderInEditModeAndOpenContextMenu = async ( test('HelloWorldContainer in edit mode hides disabledActions', async () => { const action = { id: 'FOO', - type: 'FOO' as ActionType, + type: 'FOO', getIconType: () => undefined, getDisplayName: () => 'foo', isCompatible: async () => true, @@ -252,7 +252,7 @@ test('HelloWorldContainer in edit mode hides disabledActions', async () => { test('HelloWorldContainer hides disabled badges', async () => { const action = { id: 'BAR', - type: 'BAR' as ActionType, + type: 'BAR', getIconType: () => undefined, getDisplayName: () => 'bar', isCompatible: async () => true, diff --git a/src/plugins/embeddable/public/lib/test_samples/actions/edit_mode_action.ts b/src/plugins/embeddable/public/lib/test_samples/actions/edit_mode_action.ts index bb34b474efda0..ce13c40f08d7e 100644 --- a/src/plugins/embeddable/public/lib/test_samples/actions/edit_mode_action.ts +++ b/src/plugins/embeddable/public/lib/test_samples/actions/edit_mode_action.ts @@ -17,16 +17,15 @@ * under the License. */ -import { createAction, ActionType } from '../../ui_actions'; +import { createAction } from '../../ui_actions'; import { ViewMode } from '../../types'; import { IEmbeddable } from '../..'; -// Casting to ActionType is a hack - in a real situation use -// declare module and add this id to ActionContextMapping. -export const EDIT_MODE_ACTION = 'EDIT_MODE_ACTION' as ActionType; +export const EDIT_MODE_ACTION = 'EDIT_MODE_ACTION'; export function createEditModeAction() { - return createAction({ + return createAction({ + id: EDIT_MODE_ACTION, type: EDIT_MODE_ACTION, getDisplayName: () => 'I only show up in edit mode', isCompatible: async (context: { embeddable: IEmbeddable }) => diff --git a/src/plugins/embeddable/public/lib/test_samples/actions/say_hello_action.tsx b/src/plugins/embeddable/public/lib/test_samples/actions/say_hello_action.tsx index 968caf67b1826..2aa42cbc24554 100644 --- a/src/plugins/embeddable/public/lib/test_samples/actions/say_hello_action.tsx +++ b/src/plugins/embeddable/public/lib/test_samples/actions/say_hello_action.tsx @@ -17,12 +17,10 @@ * under the License. */ -import { IncompatibleActionError, ActionType, ActionDefinitionByType } from '../../ui_actions'; +import { IncompatibleActionError, Action } from '../../ui_actions'; import { EmbeddableInput, Embeddable, EmbeddableOutput, IEmbeddable } from '../../embeddables'; -// Casting to ActionType is a hack - in a real situation use -// declare module and add this id to ActionContextMapping. -export const SAY_HELLO_ACTION = 'SAY_HELLO_ACTION' as ActionType; +export const SAY_HELLO_ACTION = 'SAY_HELLO_ACTION'; export interface FullNameEmbeddableOutput extends EmbeddableOutput { fullName: string; @@ -42,7 +40,7 @@ export interface SayHelloActionContext { message?: string; } -export class SayHelloAction implements ActionDefinitionByType { +export class SayHelloAction implements Action { public readonly type = SAY_HELLO_ACTION; public readonly id = SAY_HELLO_ACTION; diff --git a/src/plugins/embeddable/public/lib/test_samples/actions/send_message_action.tsx b/src/plugins/embeddable/public/lib/test_samples/actions/send_message_action.tsx index 04898550532df..1427a8dcb736e 100644 --- a/src/plugins/embeddable/public/lib/test_samples/actions/send_message_action.tsx +++ b/src/plugins/embeddable/public/lib/test_samples/actions/send_message_action.tsx @@ -18,16 +18,14 @@ */ import React from 'react'; import { EuiFlyoutBody } from '@elastic/eui'; -import { createAction, IncompatibleActionError, ActionType } from '../../ui_actions'; +import { createAction, IncompatibleActionError } from '../../ui_actions'; import { CoreStart } from '../../../../../../core/public'; import { toMountPoint } from '../../../../../kibana_react/public'; import { Embeddable, EmbeddableInput } from '../../embeddables'; import { GetMessageModal } from './get_message_modal'; import { FullNameEmbeddableOutput, hasFullNameOutput } from './say_hello_action'; -// Casting to ActionType is a hack - in a real situation use -// declare module and add this id to ActionContextMapping. -export const ACTION_SEND_MESSAGE = 'ACTION_SEND_MESSAGE' as ActionType; +export const ACTION_SEND_MESSAGE = 'ACTION_SEND_MESSAGE'; interface ActionContext { embeddable: Embeddable; @@ -44,7 +42,8 @@ export function createSendMessageAction(overlays: CoreStart['overlays']) { overlays.openFlyout(toMountPoint({content})); }; - return createAction({ + return createAction({ + id: ACTION_SEND_MESSAGE, type: ACTION_SEND_MESSAGE, getDisplayName: () => 'Send message', isCompatible, diff --git a/src/plugins/embeddable/public/lib/test_samples/embeddables/contact_card/contact_card.tsx b/src/plugins/embeddable/public/lib/test_samples/embeddables/contact_card/contact_card.tsx index 01228c778754b..bacc764469a78 100644 --- a/src/plugins/embeddable/public/lib/test_samples/embeddables/contact_card/contact_card.tsx +++ b/src/plugins/embeddable/public/lib/test_samples/embeddables/contact_card/contact_card.tsx @@ -24,13 +24,6 @@ import { EuiButton } from '@elastic/eui'; import * as Rx from 'rxjs'; import { UiActionsStart } from '../../../../../../ui_actions/public'; import { ContactCardEmbeddable, CONTACT_USER_TRIGGER } from './contact_card_embeddable'; -import { EmbeddableContext } from '../../../triggers'; - -declare module '../../../../../../ui_actions/public' { - export interface TriggerContextMapping { - [CONTACT_USER_TRIGGER]: EmbeddableContext; - } -} interface Props { embeddable: ContactCardEmbeddable; diff --git a/src/plugins/embeddable/public/lib/triggers/triggers.ts b/src/plugins/embeddable/public/lib/triggers/triggers.ts index d9fb063a5bb56..cb315b8804484 100644 --- a/src/plugins/embeddable/public/lib/triggers/triggers.ts +++ b/src/plugins/embeddable/public/lib/triggers/triggers.ts @@ -56,7 +56,7 @@ export type ChartActionContext = | RowClickContext; export const CONTEXT_MENU_TRIGGER = 'CONTEXT_MENU_TRIGGER'; -export const contextMenuTrigger: Trigger<'CONTEXT_MENU_TRIGGER'> = { +export const contextMenuTrigger: Trigger = { id: CONTEXT_MENU_TRIGGER, title: i18n.translate('embeddableApi.contextMenuTrigger.title', { defaultMessage: 'Context menu', @@ -67,7 +67,7 @@ export const contextMenuTrigger: Trigger<'CONTEXT_MENU_TRIGGER'> = { }; export const PANEL_BADGE_TRIGGER = 'PANEL_BADGE_TRIGGER'; -export const panelBadgeTrigger: Trigger<'PANEL_BADGE_TRIGGER'> = { +export const panelBadgeTrigger: Trigger = { id: PANEL_BADGE_TRIGGER, title: i18n.translate('embeddableApi.panelBadgeTrigger.title', { defaultMessage: 'Panel badges', @@ -78,7 +78,7 @@ export const panelBadgeTrigger: Trigger<'PANEL_BADGE_TRIGGER'> = { }; export const PANEL_NOTIFICATION_TRIGGER = 'PANEL_NOTIFICATION_TRIGGER'; -export const panelNotificationTrigger: Trigger<'PANEL_NOTIFICATION_TRIGGER'> = { +export const panelNotificationTrigger: Trigger = { id: PANEL_NOTIFICATION_TRIGGER, title: i18n.translate('embeddableApi.panelNotificationTrigger.title', { defaultMessage: 'Panel notifications', @@ -89,7 +89,7 @@ export const panelNotificationTrigger: Trigger<'PANEL_NOTIFICATION_TRIGGER'> = { }; export const SELECT_RANGE_TRIGGER = 'SELECT_RANGE_TRIGGER'; -export const selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'> = { +export const selectRangeTrigger: Trigger = { id: SELECT_RANGE_TRIGGER, title: i18n.translate('embeddableApi.selectRangeTrigger.title', { defaultMessage: 'Range selection', @@ -100,7 +100,7 @@ export const selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'> = { }; export const VALUE_CLICK_TRIGGER = 'VALUE_CLICK_TRIGGER'; -export const valueClickTrigger: Trigger<'VALUE_CLICK_TRIGGER'> = { +export const valueClickTrigger: Trigger = { id: VALUE_CLICK_TRIGGER, title: i18n.translate('embeddableApi.valueClickTrigger.title', { defaultMessage: 'Single click', diff --git a/src/plugins/embeddable/public/public.api.md b/src/plugins/embeddable/public/public.api.md index b20d5866298d5..386f1b369bef8 100644 --- a/src/plugins/embeddable/public/public.api.md +++ b/src/plugins/embeddable/public/public.api.md @@ -215,7 +215,7 @@ export const CONTEXT_MENU_TRIGGER = "CONTEXT_MENU_TRIGGER"; // Warning: (ae-missing-release-tag) "contextMenuTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const contextMenuTrigger: Trigger<'CONTEXT_MENU_TRIGGER'>; +export const contextMenuTrigger: Trigger; // Warning: (ae-missing-release-tag) "defaultEmbeddableFactoryProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -298,10 +298,8 @@ export abstract class Embeddable; + supportedTriggers(): string[]; // (undocumented) abstract readonly type: string; // (undocumented) @@ -663,7 +661,7 @@ export interface IEmbeddable; + supportedTriggers(): string[]; readonly type: string; updateInput(changes: Partial): void; } @@ -741,7 +739,7 @@ export const PANEL_NOTIFICATION_TRIGGER = "PANEL_NOTIFICATION_TRIGGER"; // Warning: (ae-missing-release-tag) "panelBadgeTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const panelBadgeTrigger: Trigger<'PANEL_BADGE_TRIGGER'>; +export const panelBadgeTrigger: Trigger; // Warning: (ae-missing-release-tag) "PanelNotFoundError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -755,7 +753,7 @@ export class PanelNotFoundError extends Error { // Warning: (ae-missing-release-tag) "panelNotificationTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const panelNotificationTrigger: Trigger<'PANEL_NOTIFICATION_TRIGGER'>; +export const panelNotificationTrigger: Trigger; // Warning: (ae-missing-release-tag) "PanelState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/src/plugins/ui_actions/public/actions/action.test.ts b/src/plugins/ui_actions/public/actions/action.test.ts index 1f76223a0d7c4..4a51c0323fa8b 100644 --- a/src/plugins/ui_actions/public/actions/action.test.ts +++ b/src/plugins/ui_actions/public/actions/action.test.ts @@ -18,14 +18,12 @@ */ import { ActionExecutionContext, createAction } from '../../../ui_actions/public'; -import { ActionType } from '../types'; import { defaultTrigger } from '../triggers'; -const sayHelloAction = createAction({ - // Casting to ActionType is a hack - in a real situation use - // declare module and add this id to ActionContextMapping. - type: 'test' as ActionType, - isCompatible: ({ amICompatible }: { amICompatible: boolean }) => Promise.resolve(amICompatible), +const sayHelloAction = createAction<{ amICompatible: boolean }>({ + id: 'test', + type: 'test', + isCompatible: ({ amICompatible }) => Promise.resolve(amICompatible), execute: () => Promise.resolve(), }); @@ -33,7 +31,7 @@ test('action is not compatible based on context', async () => { const isCompatible = await sayHelloAction.isCompatible({ amICompatible: false, trigger: defaultTrigger, - } as ActionExecutionContext); + } as ActionExecutionContext<{ amICompatible: boolean }>); expect(isCompatible).toBe(false); }); @@ -41,6 +39,6 @@ test('action is compatible based on context', async () => { const isCompatible = await sayHelloAction.isCompatible({ amICompatible: true, trigger: defaultTrigger, - } as ActionExecutionContext); + } as ActionExecutionContext<{ amICompatible: boolean }>); expect(isCompatible).toBe(true); }); diff --git a/src/plugins/ui_actions/public/actions/action.ts b/src/plugins/ui_actions/public/actions/action.ts index 8005dadd8f5ef..5d479577d4bc6 100644 --- a/src/plugins/ui_actions/public/actions/action.ts +++ b/src/plugins/ui_actions/public/actions/action.ts @@ -18,15 +18,9 @@ */ import { UiComponent } from 'src/plugins/kibana_utils/public'; -import { ActionType, ActionContextMapping, BaseContext } from '../types'; import { Presentable } from '../util/presentable'; import { Trigger } from '../triggers'; -export type ActionByType = Action; -export type ActionDefinitionByType = ActionDefinition< - ActionContextMapping[T] ->; - /** * During action execution we can provide additional information, * for example, trigger, that caused the action execution @@ -41,19 +35,18 @@ export interface ActionExecutionMeta { /** * Action methods are executed with Context from trigger + {@link ActionExecutionMeta} */ -export type ActionExecutionContext = Context & - ActionExecutionMeta; +export type ActionExecutionContext = Context & ActionExecutionMeta; /** * Simplified action context for {@link ActionDefinition} * When defining action consumer may use either it's own Context * or an ActionExecutionContext to get access to {@link ActionExecutionMeta} params */ -export type ActionDefinitionContext = +export type ActionDefinitionContext = | Context | ActionExecutionContext; -export interface Action +export interface Action extends Partial>> { /** * Determined the order when there is more than one action matched to a trigger. @@ -69,7 +62,7 @@ export interface Action /** * The action type is what determines the context shape. */ - readonly type: T; + readonly type: string; /** * Optional EUI icon type that can be displayed along with the title. @@ -117,7 +110,7 @@ export interface Action /** * A convenience interface used to register an action. */ -export interface ActionDefinition +export interface ActionDefinition extends Partial>> { /** * ID of the action that uniquely identifies this action in the actions registry. @@ -127,7 +120,7 @@ export interface ActionDefinition /** * ID of the factory for this action. Used to construct dynamic actions. */ - readonly type?: ActionType; + readonly type?: string; /** * Returns a promise that resolves to true if this item is compatible given diff --git a/src/plugins/ui_actions/public/actions/action_internal.ts b/src/plugins/ui_actions/public/actions/action_internal.ts index fe7c986bdb7ef..7cae0f68bd004 100644 --- a/src/plugins/ui_actions/public/actions/action_internal.ts +++ b/src/plugins/ui_actions/public/actions/action_internal.ts @@ -22,7 +22,6 @@ import React from 'react'; import { Action, ActionContext as Context, ActionDefinition } from './action'; import { Presentable, PresentableGrouping } from '../util/presentable'; import { uiToReactComponent } from '../../../kibana_react/public'; -import { ActionType } from '../types'; /** * @internal @@ -32,7 +31,7 @@ export class ActionInternal constructor(public readonly definition: A) {} public readonly id: string = this.definition.id; - public readonly type: ActionType = this.definition.type || ''; + public readonly type: string = this.definition.type || ''; public readonly order: number = this.definition.order || 0; public readonly MenuItem? = this.definition.MenuItem; public readonly ReactMenuItem? = this.MenuItem ? uiToReactComponent(this.MenuItem) : undefined; diff --git a/src/plugins/ui_actions/public/actions/create_action.ts b/src/plugins/ui_actions/public/actions/create_action.ts index dea21678eccea..0199812c40802 100644 --- a/src/plugins/ui_actions/public/actions/create_action.ts +++ b/src/plugins/ui_actions/public/actions/create_action.ts @@ -17,25 +17,16 @@ * under the License. */ -import { ActionContextMapping } from '../types'; -import { ActionByType } from './action'; -import { ActionType } from '../types'; -import { ActionDefinition } from './action'; +import { ActionDefinition, Action } from './action'; -interface ActionDefinitionByType - extends Omit, 'id'> { - id?: string; -} - -export function createAction( - action: ActionDefinitionByType -): ActionByType { +export function createAction( + action: ActionDefinition +): Action { return { getIconType: () => undefined, order: 0, - id: action.type, isCompatible: () => Promise.resolve(true), getDisplayName: () => '', ...action, - } as ActionByType; + } as Action; } diff --git a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.test.ts b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.test.ts index 3111a0b55084c..ac19889aa6532 100644 --- a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.test.ts +++ b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.test.ts @@ -34,6 +34,7 @@ const createTestAction = ({ grouping?: PresentableGrouping; }) => createAction({ + id: type as any, // mapping doesn't matter for this test type: type as any, // mapping doesn't matter for this test getDisplayName: () => dispayName, order, diff --git a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx index 63586ca3da1f7..aa3fd57be695a 100644 --- a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx +++ b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx @@ -24,7 +24,6 @@ import { i18n } from '@kbn/i18n'; import { uiToReactComponent } from '../../../kibana_react/public'; import { Action, ActionExecutionContext } from '../actions'; import { Trigger } from '../triggers'; -import { BaseContext } from '../types'; export const defaultTitle = i18n.translate('uiActions.actionPanel.title', { defaultMessage: 'Options', @@ -34,7 +33,7 @@ export const txtMore = i18n.translate('uiActions.actionPanel.more', { defaultMessage: 'More', }); -interface ActionWithContext { +interface ActionWithContext { action: Action; context: Context; diff --git a/src/plugins/ui_actions/public/index.ts b/src/plugins/ui_actions/public/index.ts index 7890e4bab44a3..9ac5c19033e45 100644 --- a/src/plugins/ui_actions/public/index.ts +++ b/src/plugins/ui_actions/public/index.ts @@ -39,7 +39,6 @@ export { } from './util'; export { Trigger, - TriggerContext, VISUALIZE_FIELD_TRIGGER, visualizeFieldTrigger, VISUALIZE_GEO_FIELD_TRIGGER, @@ -49,18 +48,9 @@ export { RowClickContext, } from './triggers'; export { - TriggerContextMapping, - TriggerId, - ActionContextMapping, - ActionType, VisualizeFieldContext, ACTION_VISUALIZE_FIELD, ACTION_VISUALIZE_GEO_FIELD, ACTION_VISUALIZE_LENS_FIELD, } from './types'; -export { - ActionByType, - ActionDefinitionByType, - ActionExecutionContext, - ActionExecutionMeta, -} from './actions'; +export { ActionExecutionContext, ActionExecutionMeta } from './actions'; diff --git a/src/plugins/ui_actions/public/mocks.ts b/src/plugins/ui_actions/public/mocks.ts index 759430169b613..fa24738014910 100644 --- a/src/plugins/ui_actions/public/mocks.ts +++ b/src/plugins/ui_actions/public/mocks.ts @@ -21,7 +21,6 @@ import { CoreSetup, CoreStart } from 'src/core/public'; import { UiActionsSetup, UiActionsStart } from '.'; import { plugin as pluginInitializer } from '.'; import { coreMock } from '../../../core/public/mocks'; -import { TriggerId } from './types'; export type Setup = jest.Mocked; export type Start = jest.Mocked; @@ -50,7 +49,7 @@ const createStartContract = (): Start => { getAction: jest.fn(), hasAction: jest.fn(), getTrigger: jest.fn(), - getTriggerActions: jest.fn((id: TriggerId) => []), + getTriggerActions: jest.fn((id: string) => []), getTriggerCompatibleActions: jest.fn(), registerAction: jest.fn(), registerTrigger: jest.fn(), diff --git a/src/plugins/ui_actions/public/public.api.md b/src/plugins/ui_actions/public/public.api.md index 808cb1f3fbca0..0d3ab1086904d 100644 --- a/src/plugins/ui_actions/public/public.api.md +++ b/src/plugins/ui_actions/public/public.api.md @@ -15,11 +15,10 @@ import { PublicMethodsOf } from '@kbn/utility-types'; import React from 'react'; import { UiComponent } from 'src/plugins/kibana_utils/public'; -// Warning: (ae-forgotten-export) The symbol "BaseContext" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Action" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export interface Action extends Partial>> { +export interface Action extends Partial>> { execute(context: ActionExecutionContext): Promise; getDisplayName(context: ActionExecutionContext): string; getHref?(context: ActionExecutionContext): Promise; @@ -31,7 +30,7 @@ export interface Action extend }>; order?: number; shouldAutoExecute?(context: ActionExecutionContext): Promise; - readonly type: T; + readonly type: string; } // Warning: (ae-missing-release-tag) "ACTION_VISUALIZE_FIELD" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -49,36 +48,10 @@ export const ACTION_VISUALIZE_GEO_FIELD = "ACTION_VISUALIZE_GEO_FIELD"; // @public (undocumented) export const ACTION_VISUALIZE_LENS_FIELD = "ACTION_VISUALIZE_LENS_FIELD"; -// Warning: (ae-missing-release-tag) "ActionByType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type ActionByType = Action; - -// Warning: (ae-missing-release-tag) "ActionContextMapping" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface ActionContextMapping { - // Warning: (ae-forgotten-export) The symbol "DEFAULT_ACTION" needs to be exported by the entry point index.d.ts - // - // (undocumented) - [DEFAULT_ACTION]: BaseContext; - // (undocumented) - [ACTION_VISUALIZE_FIELD]: VisualizeFieldContext; - // (undocumented) - [ACTION_VISUALIZE_GEO_FIELD]: VisualizeFieldContext; - // (undocumented) - [ACTION_VISUALIZE_LENS_FIELD]: VisualizeFieldContext; -} - -// Warning: (ae-missing-release-tag) "ActionDefinitionByType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type ActionDefinitionByType = UiActionsActionDefinition; - // Warning: (ae-missing-release-tag) "ActionExecutionContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export type ActionExecutionContext = Context & ActionExecutionMeta; +export type ActionExecutionContext = Context & ActionExecutionMeta; // Warning: (ae-missing-release-tag) "ActionExecutionMeta" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -87,22 +60,16 @@ export interface ActionExecutionMeta { trigger: Trigger; } -// Warning: (ae-missing-release-tag) "ActionType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type ActionType = keyof ActionContextMapping; - // Warning: (ae-forgotten-export) The symbol "BuildContextMenuParams" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "buildContextMenuForActions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public export function buildContextMenuForActions({ actions, title, closeMenu, }: BuildContextMenuParams): Promise; -// Warning: (ae-forgotten-export) The symbol "ActionDefinitionByType" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "createAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export function createAction(action: ActionDefinitionByType_2): ActionByType; +export function createAction(action: UiActionsActionDefinition): Action; // Warning: (ae-missing-release-tag) "IncompatibleActionError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -142,61 +109,34 @@ export interface RowClickContext { // Warning: (ae-missing-release-tag) "rowClickTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const rowClickTrigger: Trigger<'ROW_CLICK_TRIGGER'>; +export const rowClickTrigger: Trigger; // Warning: (ae-missing-release-tag) "Trigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export interface Trigger { +export interface Trigger { description?: string; - id: ID; + id: string; title?: string; } -// Warning: (ae-missing-release-tag) "TriggerContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type TriggerContext = T extends TriggerId ? TriggerContextMapping[T] : never; - -// Warning: (ae-missing-release-tag) "TriggerContextMapping" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface TriggerContextMapping { - // Warning: (ae-forgotten-export) The symbol "DEFAULT_TRIGGER" needs to be exported by the entry point index.d.ts - // Warning: (ae-forgotten-export) The symbol "TriggerContext" needs to be exported by the entry point index.d.ts - // - // (undocumented) - [DEFAULT_TRIGGER]: TriggerContext_2; - // (undocumented) - [ROW_CLICK_TRIGGER]: RowClickContext; - // (undocumented) - [VISUALIZE_FIELD_TRIGGER]: VisualizeFieldContext; - // (undocumented) - [VISUALIZE_GEO_FIELD_TRIGGER]: VisualizeFieldContext; -} - -// Warning: (ae-missing-release-tag) "TriggerId" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type TriggerId = keyof TriggerContextMapping; - // Warning: (ae-forgotten-export) The symbol "ActionDefinitionContext" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ActionDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export interface UiActionsActionDefinition extends Partial>> { +export interface UiActionsActionDefinition extends Partial>> { execute(context: ActionDefinitionContext): Promise; getHref?(context: ActionDefinitionContext): Promise; readonly id: string; isCompatible?(context: ActionDefinitionContext): Promise; shouldAutoExecute?(context: ActionDefinitionContext): Promise; - readonly type?: ActionType; + readonly type?: string; } // Warning: (ae-missing-release-tag) "Presentable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export interface UiActionsPresentable { +export interface UiActionsPresentable { getDisplayName(context: Context): string; getDisplayNameTooltip(context: Context): string; getHref?(context: Context): Promise; @@ -214,7 +154,7 @@ export interface UiActionsPresentable { // Warning: (ae-missing-release-tag) "PresentableGrouping" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export type UiActionsPresentableGrouping = Array>; +export type UiActionsPresentableGrouping = Array>; // Warning: (ae-missing-release-tag) "UiActionsService" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -225,35 +165,35 @@ export class UiActionsService { // // (undocumented) protected readonly actions: ActionRegistry; - readonly addTriggerAction: (triggerId: T, action: UiActionsActionDefinition | Action) => void; + readonly addTriggerAction: (triggerId: string, action: UiActionsActionDefinition) => void; // (undocumented) - readonly attachAction: (triggerId: T, actionId: string) => void; + readonly attachAction: (triggerId: string, actionId: string) => void; readonly clear: () => void; // (undocumented) - readonly detachAction: (triggerId: TriggerId, actionId: string) => void; + readonly detachAction: (triggerId: string, actionId: string) => void; // @deprecated (undocumented) - readonly executeTriggerActions: (triggerId: T, context: TriggerContext) => Promise; + readonly executeTriggerActions: (triggerId: string, context: object) => Promise; // Warning: (ae-forgotten-export) The symbol "UiActionsExecutionService" needs to be exported by the entry point index.d.ts // // (undocumented) readonly executionService: UiActionsExecutionService; readonly fork: () => UiActionsService; // (undocumented) - readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">; + readonly getAction: >(id: string) => Action>; // Warning: (ae-forgotten-export) The symbol "TriggerContract" needs to be exported by the entry point index.d.ts // // (undocumented) - readonly getTrigger: (triggerId: T) => TriggerContract; + readonly getTrigger: (triggerId: string) => TriggerContract; // (undocumented) - readonly getTriggerActions: (triggerId: T) => Action[]; + readonly getTriggerActions: (triggerId: string) => Action[]; // (undocumented) - readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; + readonly getTriggerCompatibleActions: (triggerId: string, context: object) => Promise; // (undocumented) readonly hasAction: (actionId: string) => boolean; // Warning: (ae-forgotten-export) The symbol "ActionContext" needs to be exported by the entry point index.d.ts // // (undocumented) - readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel">; + readonly registerAction: >(definition: A) => Action>; // (undocumented) readonly registerTrigger: (trigger: Trigger) => void; // Warning: (ae-forgotten-export) The symbol "TriggerRegistry" needs to be exported by the entry point index.d.ts @@ -314,12 +254,12 @@ export interface VisualizeFieldContext { // Warning: (ae-missing-release-tag) "visualizeFieldTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const visualizeFieldTrigger: Trigger<'VISUALIZE_FIELD_TRIGGER'>; +export const visualizeFieldTrigger: Trigger; // Warning: (ae-missing-release-tag) "visualizeGeoFieldTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const visualizeGeoFieldTrigger: Trigger<'VISUALIZE_GEO_FIELD_TRIGGER'>; +export const visualizeGeoFieldTrigger: Trigger; // Warnings were encountered during analysis: diff --git a/src/plugins/ui_actions/public/service/ui_actions_execution_service.ts b/src/plugins/ui_actions/public/service/ui_actions_execution_service.ts index 59616dcf3f38d..ea44448092a72 100644 --- a/src/plugins/ui_actions/public/service/ui_actions_execution_service.ts +++ b/src/plugins/ui_actions/public/service/ui_actions_execution_service.ts @@ -19,14 +19,13 @@ import { uniqBy } from 'lodash'; import { Action } from '../actions'; -import { BaseContext } from '../types'; import { defer as createDefer, Defer } from '../../../kibana_utils/public'; import { buildContextMenuForActions, openContextMenu } from '../context_menu'; import { Trigger } from '../triggers'; interface ExecuteActionTask { action: Action; - context: BaseContext; + context: object; trigger: Trigger; defer: Defer; alwaysShowPopup?: boolean; @@ -44,8 +43,8 @@ export class UiActionsExecutionService { context, trigger, }: { - action: Action; - context: BaseContext; + action: Action; + context: object; trigger: Trigger; }, alwaysShowPopup?: boolean diff --git a/src/plugins/ui_actions/public/service/ui_actions_service.test.ts b/src/plugins/ui_actions/public/service/ui_actions_service.test.ts index 39502c3dd17fc..137cfaeac4b67 100644 --- a/src/plugins/ui_actions/public/service/ui_actions_service.test.ts +++ b/src/plugins/ui_actions/public/service/ui_actions_service.test.ts @@ -20,19 +20,17 @@ import { UiActionsService } from './ui_actions_service'; import { Action, ActionInternal, createAction } from '../actions'; import { createHelloWorldAction } from '../tests/test_samples'; -import { TriggerRegistry, TriggerId, ActionType, ActionRegistry } from '../types'; +import { TriggerRegistry, ActionRegistry } from '../types'; import { Trigger } from '../triggers'; -// Casting to ActionType or TriggerId is a hack - in a real situation use -// declare module and add this id to the appropriate context mapping. -const FOO_TRIGGER: TriggerId = 'FOO_TRIGGER' as TriggerId; -const BAR_TRIGGER: TriggerId = 'BAR_TRIGGER' as TriggerId; -const MY_TRIGGER: TriggerId = 'MY_TRIGGER' as TriggerId; +const FOO_TRIGGER = 'FOO_TRIGGER'; +const BAR_TRIGGER = 'BAR_TRIGGER'; +const MY_TRIGGER = 'MY_TRIGGER'; const testAction1: Action = { id: 'action1', order: 1, - type: 'type1' as ActionType, + type: 'type1', execute: async () => {}, getDisplayName: () => 'test1', getIconType: () => '', @@ -42,7 +40,7 @@ const testAction1: Action = { const testAction2: Action = { id: 'action2', order: 2, - type: 'type2' as ActionType, + type: 'type2', execute: async () => {}, getDisplayName: () => 'test2', getIconType: () => '', @@ -99,7 +97,7 @@ describe('UiActionsService', () => { getDisplayName: () => 'test', getIconType: () => '', isCompatible: async () => true, - type: 'test' as ActionType, + type: 'test', }); }); @@ -111,7 +109,7 @@ describe('UiActionsService', () => { getDisplayName: () => 'test', getIconType: () => '', isCompatible: async () => true, - type: 'test' as ActionType, + type: 'test', }); expect(action).toBeInstanceOf(ActionInternal); @@ -123,7 +121,7 @@ describe('UiActionsService', () => { const action1: Action = { id: 'action1', order: 1, - type: 'type1' as ActionType, + type: 'type1', execute: async () => {}, getDisplayName: () => 'test', getIconType: () => '', @@ -132,7 +130,7 @@ describe('UiActionsService', () => { const action2: Action = { id: 'action2', order: 2, - type: 'type2' as ActionType, + type: 'type2', execute: async () => {}, getDisplayName: () => 'test', getIconType: () => '', @@ -207,7 +205,8 @@ describe('UiActionsService', () => { test('filters out actions not applicable based on the context', async () => { const service = new UiActionsService(); const action = createAction({ - type: 'test' as ActionType, + id: 'test', + type: 'test', isCompatible: ({ accept }: { accept: boolean }) => Promise.resolve(accept), execute: () => Promise.resolve(), }); @@ -238,16 +237,15 @@ describe('UiActionsService', () => { test(`throws an error with an invalid trigger ID`, async () => { const service = new UiActionsService(); - // Without the cast "as TriggerId" typescript will happily throw an error! - await expect( - service.getTriggerCompatibleActions('I do not exist' as TriggerId, {}) - ).rejects.toMatchObject(new Error('Trigger [triggerId = I do not exist] does not exist.')); + await expect(service.getTriggerCompatibleActions('I do not exist', {})).rejects.toMatchObject( + new Error('Trigger [triggerId = I do not exist] does not exist.') + ); }); test('returns empty list if trigger not attached to any action', async () => { const service = new UiActionsService(); const testTrigger: Trigger = { - id: '123' as TriggerId, + id: '123', title: '123', }; service.registerTrigger(testTrigger); @@ -445,9 +443,7 @@ describe('UiActionsService', () => { } as any; service.registerAction(action); - expect(() => - service.detachAction('i do not exist' as TriggerId, ACTION_HELLO_WORLD) - ).toThrowError( + expect(() => service.detachAction('i do not exist', ACTION_HELLO_WORLD)).toThrowError( 'No trigger [triggerId = i do not exist] exists, for detaching action [actionId = ACTION_HELLO_WORLD].' ); }); @@ -461,7 +457,7 @@ describe('UiActionsService', () => { } as any; service.registerAction(action); - expect(() => service.addTriggerAction('i do not exist' as TriggerId, action)).toThrowError( + expect(() => service.addTriggerAction('i do not exist', action)).toThrowError( 'No trigger [triggerId = i do not exist] exists, for attaching action [actionId = ACTION_HELLO_WORLD].' ); }); diff --git a/src/plugins/ui_actions/public/service/ui_actions_service.ts b/src/plugins/ui_actions/public/service/ui_actions_service.ts index ec5f3afa19c94..456341d98c5b5 100644 --- a/src/plugins/ui_actions/public/service/ui_actions_service.ts +++ b/src/plugins/ui_actions/public/service/ui_actions_service.ts @@ -17,15 +17,9 @@ * under the License. */ -import { - TriggerRegistry, - ActionRegistry, - TriggerToActionsRegistry, - TriggerId, - TriggerContextMapping, -} from '../types'; +import { TriggerRegistry, ActionRegistry, TriggerToActionsRegistry } from '../types'; import { ActionInternal, Action, ActionDefinition, ActionContext } from '../actions'; -import { Trigger, TriggerContext } from '../triggers/trigger'; +import { Trigger } from '../triggers/trigger'; import { TriggerInternal } from '../triggers/trigger_internal'; import { TriggerContract } from '../triggers/trigger_contract'; import { UiActionsExecutionService } from './ui_actions_execution_service'; @@ -67,7 +61,7 @@ export class UiActionsService { this.triggerToActions.set(trigger.id, []); }; - public readonly getTrigger = (triggerId: T): TriggerContract => { + public readonly getTrigger = (triggerId: string): TriggerContract => { const trigger = this.triggers.get(triggerId); if (!trigger) { @@ -103,7 +97,7 @@ export class UiActionsService { return this.actions.has(actionId); }; - public readonly attachAction = (triggerId: T, actionId: string): void => { + public readonly attachAction = (triggerId: string, actionId: string): void => { const trigger = this.triggers.get(triggerId); if (!trigger) { @@ -119,7 +113,7 @@ export class UiActionsService { } }; - public readonly detachAction = (triggerId: TriggerId, actionId: string) => { + public readonly detachAction = (triggerId: string, actionId: string) => { const trigger = this.triggers.get(triggerId); if (!trigger) { @@ -139,14 +133,10 @@ export class UiActionsService { /** * `addTriggerAction` is similar to `attachAction` as it attaches action to a * trigger, but it also registers the action, if it has not been registered, yet. - * - * `addTriggerAction` also infers better typing of the `action` argument. */ - public readonly addTriggerAction = ( - triggerId: T, - // The action can accept partial or no context, but if it needs context not provided - // by this type of trigger, typescript will complain. yay! - action: ActionDefinition | Action // TODO: remove `Action` https://github.com/elastic/kibana/issues/74501 + public readonly addTriggerAction = ( + triggerId: string, + action: ActionDefinition // TODO: remove `Action` https://github.com/elastic/kibana/issues/74501 ): void => { if (!this.actions.has(action.id)) this.registerAction(action); this.attachAction(triggerId, action.id); @@ -162,9 +152,7 @@ export class UiActionsService { return this.actions.get(id) as ActionInternal; }; - public readonly getTriggerActions = ( - triggerId: T - ): Array> => { + public readonly getTriggerActions = (triggerId: string): Action[] => { // This line checks if trigger exists, otherwise throws. this.getTrigger!(triggerId); @@ -174,13 +162,13 @@ export class UiActionsService { .map((actionId) => this.actions.get(actionId) as ActionInternal) .filter(Boolean); - return actions as Array>>; + return actions as Action[]; }; - public readonly getTriggerCompatibleActions = async ( - triggerId: T, - context: TriggerContextMapping[T] - ): Promise>> => { + public readonly getTriggerCompatibleActions = async ( + triggerId: string, + context: object + ): Promise => { const actions = this.getTriggerActions!(triggerId); const isCompatibles = await Promise.all( actions.map((action) => @@ -191,8 +179,7 @@ export class UiActionsService { ) ); return actions.reduce( - (acc: Array>, action, i) => - isCompatibles[i] ? [...acc, action] : acc, + (acc: Action[], action, i) => (isCompatibles[i] ? [...acc, action] : acc), [] ); }; @@ -202,11 +189,8 @@ export class UiActionsService { * * Use `plugins.uiActions.getTrigger(triggerId).exec(params)` instead. */ - public readonly executeTriggerActions = async ( - triggerId: T, - context: TriggerContext - ) => { - const trigger = this.getTrigger(triggerId); + public readonly executeTriggerActions = async (triggerId: string, context: object) => { + const trigger = this.getTrigger(triggerId); await trigger.exec(context); }; diff --git a/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts b/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts index 51ba165ba730b..6f8a45cc2e40a 100644 --- a/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts +++ b/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts @@ -21,7 +21,6 @@ import { Action, createAction } from '../actions'; import { openContextMenu } from '../context_menu'; import { uiActionsPluginMock } from '../mocks'; import { Trigger } from '../triggers'; -import { TriggerId, ActionType } from '../types'; import { waitFor } from '@testing-library/dom'; jest.mock('../context_menu'); @@ -31,17 +30,13 @@ const openContextMenuSpy = (openContextMenu as any) as jest.SpyInstance; const CONTACT_USER_TRIGGER = 'CONTACT_USER_TRIGGER'; -// Casting to ActionType is a hack - in a real situation use -// declare module and add this id to ActionContextMapping. -const TEST_ACTION_TYPE = 'TEST_ACTION_TYPE' as ActionType; - function createTestAction( type: string, checkCompatibility: (context: C) => boolean, autoExecutable = false ): Action { - return createAction({ - type: type as ActionType, + return createAction({ + type, id: type, isCompatible: (context: C) => Promise.resolve(checkCompatibility(context)), execute: (context) => executeFn(context), @@ -67,7 +62,7 @@ beforeEach(reset); test('executes a single action mapped to a trigger', async () => { const { setup, doStart } = uiActions; const trigger: Trigger = { - id: 'MY-TRIGGER' as TriggerId, + id: 'MY-TRIGGER', title: 'My trigger', }; const action = createTestAction('test1', () => true); @@ -77,7 +72,7 @@ test('executes a single action mapped to a trigger', async () => { const context = {}; const start = doStart(); - await start.executeTriggerActions('MY-TRIGGER' as TriggerId, context); + await start.executeTriggerActions('MY-TRIGGER', context); jest.runAllTimers(); @@ -88,7 +83,7 @@ test('executes a single action mapped to a trigger', async () => { test("doesn't throw an error if there are no compatible actions to execute", async () => { const { setup, doStart } = uiActions; const trigger: Trigger = { - id: 'MY-TRIGGER' as TriggerId, + id: 'MY-TRIGGER', title: 'My trigger', }; @@ -96,15 +91,13 @@ test("doesn't throw an error if there are no compatible actions to execute", asy const context = {}; const start = doStart(); - await expect( - start.executeTriggerActions('MY-TRIGGER' as TriggerId, context) - ).resolves.toBeUndefined(); + await expect(start.executeTriggerActions('MY-TRIGGER', context)).resolves.toBeUndefined(); }); test('does not execute an incompatible action', async () => { const { setup, doStart } = uiActions; const trigger: Trigger = { - id: 'MY-TRIGGER' as TriggerId, + id: 'MY-TRIGGER', title: 'My trigger', }; const action = createTestAction<{ name: string }>( @@ -119,7 +112,7 @@ test('does not execute an incompatible action', async () => { const context = { name: 'executeme', }; - await start.executeTriggerActions('MY-TRIGGER' as TriggerId, context); + await start.executeTriggerActions('MY-TRIGGER', context); jest.runAllTimers(); @@ -129,7 +122,7 @@ test('does not execute an incompatible action', async () => { test('shows a context menu when more than one action is mapped to a trigger', async () => { const { setup, doStart } = uiActions; const trigger: Trigger = { - id: 'MY-TRIGGER' as TriggerId, + id: 'MY-TRIGGER', title: 'My trigger', }; const action1 = createTestAction('test1', () => true); @@ -143,7 +136,7 @@ test('shows a context menu when more than one action is mapped to a trigger', as const start = doStart(); const context = {}; - await start.getTrigger('MY-TRIGGER' as TriggerId)!.exec(context); + await start.getTrigger('MY-TRIGGER')!.exec(context); jest.runAllTimers(); @@ -156,7 +149,7 @@ test('shows a context menu when more than one action is mapped to a trigger', as test('shows a context menu when there is only one action mapped to a trigger and "alwaysShowPopup" is set', async () => { const { setup, doStart } = uiActions; const trigger: Trigger = { - id: 'MY-TRIGGER' as TriggerId, + id: 'MY-TRIGGER', title: 'My trigger', }; const action1 = createTestAction('test1', () => true); @@ -168,7 +161,7 @@ test('shows a context menu when there is only one action mapped to a trigger and const start = doStart(); const context = {}; - await start.getTrigger('MY-TRIGGER' as TriggerId)!.exec(context, true); + await start.getTrigger('MY-TRIGGER')!.exec(context, true); jest.runAllTimers(); @@ -181,7 +174,7 @@ test('shows a context menu when there is only one action mapped to a trigger and test('passes whole action context to isCompatible()', async () => { const { setup, doStart } = uiActions; const trigger = { - id: 'MY-TRIGGER' as TriggerId, + id: 'MY-TRIGGER', title: 'My trigger', }; const action = createTestAction<{ foo: string }>('test', ({ foo }) => { @@ -195,14 +188,14 @@ test('passes whole action context to isCompatible()', async () => { const start = doStart(); const context = { foo: 'bar' }; - await start.executeTriggerActions('MY-TRIGGER' as TriggerId, context); + await start.executeTriggerActions('MY-TRIGGER', context); jest.runAllTimers(); }); test("doesn't show a context menu for auto executable actions", async () => { const { setup, doStart } = uiActions; const trigger: Trigger = { - id: 'MY-TRIGGER' as TriggerId, + id: 'MY-TRIGGER', title: 'My trigger', }; const action1 = createTestAction('test1', () => true, true); @@ -216,7 +209,7 @@ test("doesn't show a context menu for auto executable actions", async () => { const start = doStart(); const context = {}; - await start.executeTriggerActions('MY-TRIGGER' as TriggerId, context); + await start.executeTriggerActions('MY-TRIGGER', context); jest.runAllTimers(); @@ -229,7 +222,7 @@ test("doesn't show a context menu for auto executable actions", async () => { test('passes trigger into execute', async () => { const { setup, doStart } = uiActions; const trigger = { - id: 'MY-TRIGGER' as TriggerId, + id: 'MY-TRIGGER', title: 'My trigger', }; const action = createTestAction<{ foo: string }>('test', () => true); @@ -240,7 +233,7 @@ test('passes trigger into execute', async () => { const start = doStart(); const context = { foo: 'bar' }; - await start.executeTriggerActions('MY-TRIGGER' as TriggerId, context); + await start.executeTriggerActions('MY-TRIGGER', context); jest.runAllTimers(); expect(executeFn).toBeCalledWith({ ...context, diff --git a/src/plugins/ui_actions/public/tests/get_trigger_actions.test.ts b/src/plugins/ui_actions/public/tests/get_trigger_actions.test.ts index 55ccac42ff255..ddae251bb83d2 100644 --- a/src/plugins/ui_actions/public/tests/get_trigger_actions.test.ts +++ b/src/plugins/ui_actions/public/tests/get_trigger_actions.test.ts @@ -19,17 +19,16 @@ import { ActionInternal, Action } from '../actions'; import { uiActionsPluginMock } from '../mocks'; -import { TriggerId, ActionType } from '../types'; const action1: Action = { id: 'action1', order: 1, - type: 'type1' as ActionType, + type: 'type1', } as any; const action2: Action = { id: 'action2', order: 2, - type: 'type2' as ActionType, + type: 'type2', } as any; test('returns actions set on trigger', () => { @@ -38,24 +37,24 @@ test('returns actions set on trigger', () => { setup.registerAction(action2); setup.registerTrigger({ description: 'foo', - id: 'trigger' as TriggerId, + id: 'trigger', title: 'baz', }); const start = doStart(); - const list0 = start.getTriggerActions('trigger' as TriggerId); + const list0 = start.getTriggerActions('trigger'); expect(list0).toHaveLength(0); - setup.addTriggerAction('trigger' as TriggerId, action1); - const list1 = start.getTriggerActions('trigger' as TriggerId); + setup.addTriggerAction('trigger', action1); + const list1 = start.getTriggerActions('trigger'); expect(list1).toHaveLength(1); expect(list1[0]).toBeInstanceOf(ActionInternal); expect(list1[0].id).toBe(action1.id); - setup.addTriggerAction('trigger' as TriggerId, action2); - const list2 = start.getTriggerActions('trigger' as TriggerId); + setup.addTriggerAction('trigger', action2); + const list2 = start.getTriggerActions('trigger'); expect(list2).toHaveLength(2); expect(!!list2.find(({ id }: any) => id === 'action1')).toBe(true); diff --git a/src/plugins/ui_actions/public/tests/get_trigger_compatible_actions.test.ts b/src/plugins/ui_actions/public/tests/get_trigger_compatible_actions.test.ts index 21dd17ed82e3f..400a9453fe267 100644 --- a/src/plugins/ui_actions/public/tests/get_trigger_compatible_actions.test.ts +++ b/src/plugins/ui_actions/public/tests/get_trigger_compatible_actions.test.ts @@ -21,23 +21,23 @@ import { uiActionsPluginMock } from '../mocks'; import { createHelloWorldAction } from '../tests/test_samples'; import { Action, createAction } from '../actions'; import { Trigger } from '../triggers'; -import { TriggerId, ActionType } from '../types'; -let action: Action<{ name: string }, ActionType>; +let action: Action<{ name: string }>; let uiActions: ReturnType; beforeEach(() => { uiActions = uiActionsPluginMock.createPlugin(); action = createAction({ - type: 'test' as ActionType, + id: 'test', + type: 'test', execute: () => Promise.resolve(), }); uiActions.setup.registerAction(action); uiActions.setup.registerTrigger({ - id: 'trigger' as TriggerId, + id: 'trigger', title: 'trigger', }); - uiActions.setup.addTriggerAction('trigger' as TriggerId, action); + uiActions.setup.addTriggerAction('trigger', action); }); test('can register action', async () => { @@ -54,14 +54,14 @@ test('getTriggerCompatibleActions returns attached actions', async () => { setup.registerAction(helloWorldAction); const testTrigger: Trigger = { - id: 'MY-TRIGGER' as TriggerId, + id: 'MY-TRIGGER', title: 'My trigger', }; setup.registerTrigger(testTrigger); - setup.addTriggerAction('MY-TRIGGER' as TriggerId, helloWorldAction); + setup.addTriggerAction('MY-TRIGGER', helloWorldAction); const start = doStart(); - const actions = await start.getTriggerCompatibleActions('MY-TRIGGER' as TriggerId, {}); + const actions = await start.getTriggerCompatibleActions('MY-TRIGGER', {}); expect(actions.length).toBe(1); expect(actions[0].id).toBe(helloWorldAction.id); @@ -70,7 +70,8 @@ test('getTriggerCompatibleActions returns attached actions', async () => { test('filters out actions not applicable based on the context', async () => { const { setup, doStart } = uiActions; const action1 = createAction({ - type: 'test1' as ActionType, + id: 'test1', + type: 'test1', isCompatible: async (context: { accept: boolean }) => { return Promise.resolve(context.accept); }, @@ -78,7 +79,7 @@ test('filters out actions not applicable based on the context', async () => { }); const testTrigger: Trigger = { - id: 'MY-TRIGGER2' as TriggerId, + id: 'MY-TRIGGER2', title: 'My trigger', }; @@ -100,15 +101,15 @@ test(`throws an error with an invalid trigger ID`, async () => { const { doStart } = uiActions; const start = doStart(); - await expect( - start.getTriggerCompatibleActions('I do not exist' as TriggerId, {}) - ).rejects.toMatchObject(new Error('Trigger [triggerId = I do not exist] does not exist.')); + await expect(start.getTriggerCompatibleActions('I do not exist', {})).rejects.toMatchObject( + new Error('Trigger [triggerId = I do not exist] does not exist.') + ); }); test(`with a trigger mapping that maps to an non-existing action returns empty list`, async () => { const { setup, doStart } = uiActions; const testTrigger: Trigger = { - id: '123' as TriggerId, + id: '123', title: '123', }; setup.registerTrigger(testTrigger); diff --git a/src/plugins/ui_actions/public/tests/test_samples/hello_world_action.tsx b/src/plugins/ui_actions/public/tests/test_samples/hello_world_action.tsx index a4cfe172dd109..f9e1c0261e1a1 100644 --- a/src/plugins/ui_actions/public/tests/test_samples/hello_world_action.tsx +++ b/src/plugins/ui_actions/public/tests/test_samples/hello_world_action.tsx @@ -20,9 +20,8 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiBadge, EuiFlyoutBody } from '@elastic/eui'; import { CoreStart } from 'src/core/public'; -import { createAction, ActionByType } from '../../actions'; +import { createAction, Action } from '../../actions'; import { toMountPoint, reactToUiComponent } from '../../../../kibana_react/public'; -import { ActionType } from '../../types'; const ReactMenuItem: React.FC = () => { return ( @@ -37,14 +36,11 @@ const ReactMenuItem: React.FC = () => { const UiMenuItem = reactToUiComponent(ReactMenuItem); -// Casting to ActionType is a hack - in a real situation use -// declare module and add this id to ActionContextMapping. -export const ACTION_HELLO_WORLD = 'ACTION_HELLO_WORLD' as ActionType; +export const ACTION_HELLO_WORLD = 'ACTION_HELLO_WORLD'; -export function createHelloWorldAction( - overlays: CoreStart['overlays'] -): ActionByType { - return createAction({ +export function createHelloWorldAction(overlays: CoreStart['overlays']): Action { + return createAction({ + id: ACTION_HELLO_WORLD, type: ACTION_HELLO_WORLD, getIconType: () => 'lock', MenuItem: UiMenuItem, diff --git a/src/plugins/ui_actions/public/triggers/default_trigger.ts b/src/plugins/ui_actions/public/triggers/default_trigger.ts index 74be0243bdac5..107cb3bda5b7d 100644 --- a/src/plugins/ui_actions/public/triggers/default_trigger.ts +++ b/src/plugins/ui_actions/public/triggers/default_trigger.ts @@ -20,7 +20,7 @@ import { Trigger } from '.'; export const DEFAULT_TRIGGER = ''; -export const defaultTrigger: Trigger<''> = { +export const defaultTrigger: Trigger = { id: DEFAULT_TRIGGER, title: 'Unknown', description: 'Unknown trigger.', diff --git a/src/plugins/ui_actions/public/triggers/row_click_trigger.ts b/src/plugins/ui_actions/public/triggers/row_click_trigger.ts index 0fc261b3e1fb3..3d47e017675c3 100644 --- a/src/plugins/ui_actions/public/triggers/row_click_trigger.ts +++ b/src/plugins/ui_actions/public/triggers/row_click_trigger.ts @@ -23,7 +23,7 @@ import { Datatable } from '../../../expressions'; export const ROW_CLICK_TRIGGER = 'ROW_CLICK_TRIGGER'; -export const rowClickTrigger: Trigger<'ROW_CLICK_TRIGGER'> = { +export const rowClickTrigger: Trigger = { id: ROW_CLICK_TRIGGER, title: i18n.translate('uiActions.triggers.rowClickTitle', { defaultMessage: 'Table row click', diff --git a/src/plugins/ui_actions/public/triggers/trigger.ts b/src/plugins/ui_actions/public/triggers/trigger.ts index 1b1231c132dde..b4def56d21395 100644 --- a/src/plugins/ui_actions/public/triggers/trigger.ts +++ b/src/plugins/ui_actions/public/triggers/trigger.ts @@ -17,8 +17,6 @@ * under the License. */ -import { TriggerContextMapping, TriggerId } from '../types'; - /** * This is a convenience interface used to register a *trigger*. * @@ -30,11 +28,11 @@ import { TriggerContextMapping, TriggerId } from '../types'; * trigger is *called* it first displays a context menu for user to pick a * single action to execute. */ -export interface Trigger { +export interface Trigger { /** * Unique name of the trigger as identified in `ui_actions` plugin trigger registry. */ - id: ID; + id: string; /** * User friendly name of the trigger. @@ -46,5 +44,3 @@ export interface Trigger { */ description?: string; } - -export type TriggerContext = T extends TriggerId ? TriggerContextMapping[T] : never; diff --git a/src/plugins/ui_actions/public/triggers/trigger_contract.ts b/src/plugins/ui_actions/public/triggers/trigger_contract.ts index 7e7fba0ba80d3..95e856f4d3eaa 100644 --- a/src/plugins/ui_actions/public/triggers/trigger_contract.ts +++ b/src/plugins/ui_actions/public/triggers/trigger_contract.ts @@ -18,16 +18,15 @@ */ import { TriggerInternal } from './trigger_internal'; -import { TriggerId, TriggerContextMapping } from '../types'; /** * This is a public representation of a trigger that is provided to other plugins. */ -export class TriggerContract { +export class TriggerContract { /** * Unique name of the trigger as identified in `ui_actions` plugin trigger registry. */ - public readonly id: T; + public readonly id: string; /** * User friendly name of the trigger. @@ -39,7 +38,7 @@ export class TriggerContract { */ public readonly description?: string; - constructor(private readonly internal: TriggerInternal) { + constructor(private readonly internal: TriggerInternal) { this.id = this.internal.trigger.id; this.title = this.internal.trigger.title; this.description = this.internal.trigger.description; @@ -48,7 +47,7 @@ export class TriggerContract { /** * Use this method to execute action attached to this trigger. */ - public readonly exec = async (context: TriggerContextMapping[T], alwaysShowPopup?: boolean) => { + public readonly exec = async (context: Context, alwaysShowPopup?: boolean) => { await this.internal.execute(context, alwaysShowPopup); }; } diff --git a/src/plugins/ui_actions/public/triggers/trigger_internal.ts b/src/plugins/ui_actions/public/triggers/trigger_internal.ts index fd43a020504c0..e78b2beaabc8e 100644 --- a/src/plugins/ui_actions/public/triggers/trigger_internal.ts +++ b/src/plugins/ui_actions/public/triggers/trigger_internal.ts @@ -20,18 +20,17 @@ import { Trigger } from './trigger'; import { TriggerContract } from './trigger_contract'; import { UiActionsService } from '../service'; -import { TriggerId, TriggerContextMapping } from '../types'; /** * Internal representation of a trigger kept for consumption only internally * within `ui_actions` plugin. */ -export class TriggerInternal { - public readonly contract = new TriggerContract(this); +export class TriggerInternal { + public readonly contract: TriggerContract = new TriggerContract(this); - constructor(public readonly service: UiActionsService, public readonly trigger: Trigger) {} + constructor(public readonly service: UiActionsService, public readonly trigger: Trigger) {} - public async execute(context: TriggerContextMapping[T], alwaysShowPopup?: boolean) { + public async execute(context: Context, alwaysShowPopup?: boolean) { const triggerId = this.trigger.id; const actions = await this.service.getTriggerCompatibleActions!(triggerId, context); diff --git a/src/plugins/ui_actions/public/triggers/visualize_field_trigger.ts b/src/plugins/ui_actions/public/triggers/visualize_field_trigger.ts index 4f3c5f613eddf..0c85f4d38dee4 100644 --- a/src/plugins/ui_actions/public/triggers/visualize_field_trigger.ts +++ b/src/plugins/ui_actions/public/triggers/visualize_field_trigger.ts @@ -20,7 +20,7 @@ import { Trigger } from '.'; export const VISUALIZE_FIELD_TRIGGER = 'VISUALIZE_FIELD_TRIGGER'; -export const visualizeFieldTrigger: Trigger<'VISUALIZE_FIELD_TRIGGER'> = { +export const visualizeFieldTrigger: Trigger = { id: VISUALIZE_FIELD_TRIGGER, title: 'Visualize field', description: 'Triggered when user wants to visualize a field.', diff --git a/src/plugins/ui_actions/public/triggers/visualize_geo_field_trigger.ts b/src/plugins/ui_actions/public/triggers/visualize_geo_field_trigger.ts index 5582b3b42660c..0ee0be3a644d4 100644 --- a/src/plugins/ui_actions/public/triggers/visualize_geo_field_trigger.ts +++ b/src/plugins/ui_actions/public/triggers/visualize_geo_field_trigger.ts @@ -20,7 +20,7 @@ import { Trigger } from '.'; export const VISUALIZE_GEO_FIELD_TRIGGER = 'VISUALIZE_GEO_FIELD_TRIGGER'; -export const visualizeGeoFieldTrigger: Trigger<'VISUALIZE_GEO_FIELD_TRIGGER'> = { +export const visualizeGeoFieldTrigger: Trigger = { id: VISUALIZE_GEO_FIELD_TRIGGER, title: 'Visualize Geo field', description: 'Triggered when user wants to visualize a geo field.', diff --git a/src/plugins/ui_actions/public/types.ts b/src/plugins/ui_actions/public/types.ts index 62fac245514cd..dc3b25f69f513 100644 --- a/src/plugins/ui_actions/public/types.ts +++ b/src/plugins/ui_actions/public/types.ts @@ -19,17 +19,10 @@ import { ActionInternal } from './actions/action_internal'; import { TriggerInternal } from './triggers/trigger_internal'; -import { - ROW_CLICK_TRIGGER, - VISUALIZE_FIELD_TRIGGER, - VISUALIZE_GEO_FIELD_TRIGGER, - DEFAULT_TRIGGER, - RowClickContext, -} from './triggers'; -export type TriggerRegistry = Map>; +export type TriggerRegistry = Map>; export type ActionRegistry = Map; -export type TriggerToActionsRegistry = Map; +export type TriggerToActionsRegistry = Map; export interface VisualizeFieldContext { fieldName: string; @@ -37,27 +30,6 @@ export interface VisualizeFieldContext { contextualFields?: string[]; } -export type TriggerId = keyof TriggerContextMapping; - -export type BaseContext = object; -export type TriggerContext = BaseContext; - -export interface TriggerContextMapping { - [DEFAULT_TRIGGER]: TriggerContext; - [ROW_CLICK_TRIGGER]: RowClickContext; - [VISUALIZE_FIELD_TRIGGER]: VisualizeFieldContext; - [VISUALIZE_GEO_FIELD_TRIGGER]: VisualizeFieldContext; -} - -const DEFAULT_ACTION = ''; export const ACTION_VISUALIZE_FIELD = 'ACTION_VISUALIZE_FIELD'; export const ACTION_VISUALIZE_GEO_FIELD = 'ACTION_VISUALIZE_GEO_FIELD'; export const ACTION_VISUALIZE_LENS_FIELD = 'ACTION_VISUALIZE_LENS_FIELD'; -export type ActionType = keyof ActionContextMapping; - -export interface ActionContextMapping { - [DEFAULT_ACTION]: BaseContext; - [ACTION_VISUALIZE_FIELD]: VisualizeFieldContext; - [ACTION_VISUALIZE_GEO_FIELD]: VisualizeFieldContext; - [ACTION_VISUALIZE_LENS_FIELD]: VisualizeFieldContext; -} diff --git a/src/plugins/ui_actions/public/util/presentable.ts b/src/plugins/ui_actions/public/util/presentable.ts index 59440d6c75976..c586a996920ac 100644 --- a/src/plugins/ui_actions/public/util/presentable.ts +++ b/src/plugins/ui_actions/public/util/presentable.ts @@ -22,7 +22,7 @@ import { UiComponent } from 'src/plugins/kibana_utils/public'; /** * Represents something that can be displayed to user in UI. */ -export interface Presentable { +export interface Presentable { /** * ID that uniquely identifies this object. */ @@ -77,11 +77,11 @@ export interface Presentable { readonly grouping?: PresentableGrouping; } -export interface PresentableGroup +export interface PresentableGroup extends Partial< Pick, 'getDisplayName' | 'getDisplayNameTooltip' | 'getIconType' | 'order'> > { id: string; } -export type PresentableGrouping = Array>; +export type PresentableGrouping = Array>; diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index 5661acc26fdb6..3956f930758d7 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -49,7 +49,6 @@ import { Vis, SerializedVis } from '../vis'; import { getExpressions, getUiActions } from '../services'; import { VIS_EVENT_TO_TRIGGER } from './events'; import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory'; -import { TriggerId } from '../../../ui_actions/public'; import { SavedObjectAttributes } from '../../../../core/types'; import { SavedVisualizationsLoader } from '../saved_visualizations'; import { VisSavedObject } from '../types'; @@ -414,7 +413,7 @@ export class VisualizeEmbeddable }); }; - public supportedTriggers(): TriggerId[] { + public supportedTriggers(): string[] { return this.vis.type.getSupportedTriggers?.() ?? []; } diff --git a/src/plugins/visualizations/public/vis_types/types.ts b/src/plugins/visualizations/public/vis_types/types.ts index 6ea44dc360559..5b75d065118da 100644 --- a/src/plugins/visualizations/public/vis_types/types.ts +++ b/src/plugins/visualizations/public/vis_types/types.ts @@ -23,7 +23,6 @@ import { Adapters } from 'src/plugins/inspector'; import { IndexPattern } from 'src/plugins/data/public'; import { VisEditorConstructor } from 'src/plugins/visualize/public'; import { ISchemas } from 'src/plugins/vis_default_editor/public'; -import { TriggerContextMapping } from '../../../ui_actions/public'; import { Vis, VisParams, VisToExpressionAst, VisualizationControllerConstructor } from '../types'; export interface VisTypeOptions { @@ -64,7 +63,7 @@ export interface VisType { /** * If given, it will return the supported triggers for this vis. */ - readonly getSupportedTriggers?: () => Array; + readonly getSupportedTriggers?: () => string[]; /** * Some visualizations are created without SearchSource and may change the used indexes during the visualization configuration. diff --git a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts index fc5dfd4e123fb..c05f42d684dbe 100644 --- a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts +++ b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -import { TriggerContextMapping } from '../../../ui_actions/public'; export interface VisualizationListItem { editUrl: string; @@ -28,7 +27,7 @@ export interface VisualizationListItem { savedObjectType: string; title: string; description?: string; - getSupportedTriggers?: () => Array; + getSupportedTriggers?: () => string[]; typeTitle: string; image?: string; } @@ -59,7 +58,7 @@ export interface VisTypeAlias { description: string; note?: string; disabled?: boolean; - getSupportedTriggers?: () => Array; + getSupportedTriggers?: () => string[]; stage: 'experimental' | 'beta' | 'production'; appExtensions?: { diff --git a/src/plugins/visualize/public/actions/visualize_field_action.ts b/src/plugins/visualize/public/actions/visualize_field_action.ts index e570ed5e49e6a..a825ad9e60641 100644 --- a/src/plugins/visualize/public/actions/visualize_field_action.ts +++ b/src/plugins/visualize/public/actions/visualize_field_action.ts @@ -32,7 +32,7 @@ import { import { VISUALIZE_APP_URL_GENERATOR, VisualizeUrlGeneratorState } from '../url_generator'; import { AGGS_TERMS_SIZE_SETTING } from '../../common/constants'; -export const visualizeFieldAction = createAction({ +export const visualizeFieldAction = createAction({ type: ACTION_VISUALIZE_FIELD, id: ACTION_VISUALIZE_FIELD, getDisplayName: () => diff --git a/test/plugin_functional/plugins/kbn_sample_panel_action/public/sample_panel_action.tsx b/test/plugin_functional/plugins/kbn_sample_panel_action/public/sample_panel_action.tsx index 18e45c22abaca..1d79fcae3c1a3 100644 --- a/test/plugin_functional/plugins/kbn_sample_panel_action/public/sample_panel_action.tsx +++ b/test/plugin_functional/plugins/kbn_sample_panel_action/public/sample_panel_action.tsx @@ -21,19 +21,18 @@ import { EuiFlyoutBody, EuiFlyoutHeader, EuiTitle } from '@elastic/eui'; import React from 'react'; import { IEmbeddable } from '../../../../../src/plugins/embeddable/public'; -import { createAction, ActionType } from '../../../../../src/plugins/ui_actions/public'; +import { createAction } from '../../../../../src/plugins/ui_actions/public'; import { toMountPoint } from '../../../../../src/plugins/kibana_react/public'; -// Casting to ActionType is a hack - in a real situation use -// declare module and add this id to ActionContextMapping. -export const SAMPLE_PANEL_ACTION = 'samplePanelAction' as ActionType; +export const SAMPLE_PANEL_ACTION = 'samplePanelAction'; export interface SamplePanelActionContext { embeddable: IEmbeddable; } export function createSamplePanelAction(getStartServices: CoreSetup['getStartServices']) { - return createAction({ + return createAction({ + id: SAMPLE_PANEL_ACTION, type: SAMPLE_PANEL_ACTION, getDisplayName: () => 'Sample Panel Action', execute: async ({ embeddable }: SamplePanelActionContext) => { diff --git a/test/plugin_functional/plugins/kbn_sample_panel_action/public/sample_panel_link.ts b/test/plugin_functional/plugins/kbn_sample_panel_action/public/sample_panel_link.ts index faa774b8485b1..ec6a2286ca33f 100644 --- a/test/plugin_functional/plugins/kbn_sample_panel_action/public/sample_panel_link.ts +++ b/test/plugin_functional/plugins/kbn_sample_panel_action/public/sample_panel_link.ts @@ -16,14 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -import { Action, createAction, ActionType } from '../../../../../src/plugins/ui_actions/public'; +import { Action, createAction } from '../../../../../src/plugins/ui_actions/public'; -// Casting to ActionType is a hack - in a real situation use -// declare module and add this id to ActionContextMapping. -export const SAMPLE_PANEL_LINK = 'samplePanelLink' as ActionType; +export const SAMPLE_PANEL_LINK = 'samplePanelLink'; export const createSamplePanelLink = (): Action => - createAction({ + createAction({ + id: SAMPLE_PANEL_LINK, type: SAMPLE_PANEL_LINK, getDisplayName: () => 'Sample panel Link', execute: async () => { diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app1_hello_world_drilldown/app1_hello_world_drilldown.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app1_hello_world_drilldown/app1_hello_world_drilldown.tsx index 25de2f5953f31..fd1c708b80bf2 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app1_hello_world_drilldown/app1_hello_world_drilldown.tsx +++ b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app1_hello_world_drilldown/app1_hello_world_drilldown.tsx @@ -23,7 +23,7 @@ export type CollectConfigProps = CollectConfigPropsBase { +export class App1HelloWorldDrilldown implements Drilldown { public readonly id = APP1_HELLO_WORLD_DRILLDOWN; public readonly order = 8; diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app1_to_dashboard_drilldown/app1_to_dashboard_drilldown.ts b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app1_to_dashboard_drilldown/app1_to_dashboard_drilldown.ts index 058b52c78b427..a6c3ce652f2c9 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app1_to_dashboard_drilldown/app1_to_dashboard_drilldown.ts +++ b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app1_to_dashboard_drilldown/app1_to_dashboard_drilldown.ts @@ -13,13 +13,12 @@ import { KibanaURL } from '../../../../../../src/plugins/share/public'; export const APP1_TO_DASHBOARD_DRILLDOWN = 'APP1_TO_DASHBOARD_DRILLDOWN'; -type Trigger = typeof SAMPLE_APP1_CLICK_TRIGGER; type Context = SampleApp1ClickContext; -export class App1ToDashboardDrilldown extends AbstractDashboardDrilldown { +export class App1ToDashboardDrilldown extends AbstractDashboardDrilldown { public readonly id = APP1_TO_DASHBOARD_DRILLDOWN; - public readonly supportedTriggers = () => [SAMPLE_APP1_CLICK_TRIGGER] as Trigger[]; + public readonly supportedTriggers = () => [SAMPLE_APP1_CLICK_TRIGGER]; protected async getURL(config: Config, context: Context): Promise { const path = await this.urlGenerator.createUrl({ diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app2_to_dashboard_drilldown/app2_to_dashboard_drilldown.ts b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app2_to_dashboard_drilldown/app2_to_dashboard_drilldown.ts index 33bf54d4b4cc2..9a59a715be5f8 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app2_to_dashboard_drilldown/app2_to_dashboard_drilldown.ts +++ b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/app2_to_dashboard_drilldown/app2_to_dashboard_drilldown.ts @@ -13,13 +13,12 @@ import { KibanaURL } from '../../../../../../src/plugins/share/public'; export const APP2_TO_DASHBOARD_DRILLDOWN = 'APP2_TO_DASHBOARD_DRILLDOWN'; -type Trigger = typeof SAMPLE_APP2_CLICK_TRIGGER; type Context = SampleApp2ClickContext; -export class App2ToDashboardDrilldown extends AbstractDashboardDrilldown { +export class App2ToDashboardDrilldown extends AbstractDashboardDrilldown { public readonly id = APP2_TO_DASHBOARD_DRILLDOWN; - public readonly supportedTriggers = () => [SAMPLE_APP2_CLICK_TRIGGER] as Trigger[]; + public readonly supportedTriggers = () => [SAMPLE_APP2_CLICK_TRIGGER]; protected async getURL(config: Config, context: Context): Promise { const path = await this.urlGenerator.createUrl({ diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_hello_world_drilldown/index.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_hello_world_drilldown/index.tsx index 50ad350cd90b9..8c90b38358fd6 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_hello_world_drilldown/index.tsx +++ b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_hello_world_drilldown/index.tsx @@ -23,8 +23,7 @@ export type Config = { const SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN = 'SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN'; -export class DashboardHelloWorldDrilldown - implements Drilldown { +export class DashboardHelloWorldDrilldown implements Drilldown { public readonly id = SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN; public readonly order = 6; @@ -33,7 +32,7 @@ export class DashboardHelloWorldDrilldown public readonly euiIcon = 'cheer'; - supportedTriggers(): Array { + supportedTriggers(): string[] { return [VALUE_CLICK_TRIGGER, SELECT_RANGE_TRIGGER]; } diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_hello_world_only_range_select_drilldown/index.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_hello_world_only_range_select_drilldown/index.tsx index 4e5b3187af42b..cac454d747318 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_hello_world_only_range_select_drilldown/index.tsx +++ b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_hello_world_only_range_select_drilldown/index.tsx @@ -23,7 +23,7 @@ const SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN_ONLY_RANGE_SELECT = 'SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN_ONLY_RANGE_SELECT'; export class DashboardHelloWorldOnlyRangeSelectDrilldown - implements Drilldown { + implements Drilldown { public readonly id = SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN_ONLY_RANGE_SELECT; public readonly order = 7; @@ -57,7 +57,7 @@ export class DashboardHelloWorldOnlyRangeSelectDrilldown public readonly isConfigValid = ( config: Config, - context: BaseActionFactoryContext + context: BaseActionFactoryContext ): config is Config => { // eslint-disable-next-line no-console console.log('Showcasing, that can access action factory context:', context); diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_to_discover_drilldown/drilldown.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_to_discover_drilldown/drilldown.tsx index 2f161efe6f388..d876143a036fd 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_to_discover_drilldown/drilldown.tsx +++ b/x-pack/examples/ui_actions_enhanced_examples/public/drilldowns/dashboard_to_discover_drilldown/drilldown.tsx @@ -13,7 +13,10 @@ import { CollectConfigContainer } from './collect_config_container'; import { SAMPLE_DASHBOARD_TO_DISCOVER_DRILLDOWN } from './constants'; import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../../plugins/ui_actions_enhanced/public'; import { txtGoToDiscover } from './i18n'; -import { APPLY_FILTER_TRIGGER } from '../../../../../../src/plugins/data/public'; +import { + ApplyGlobalFilterActionContext, + APPLY_FILTER_TRIGGER, +} from '../../../../../../src/plugins/data/public'; const isOutputWithIndexPatterns = ( output: unknown @@ -27,7 +30,7 @@ export interface Params { } export class DashboardToDiscoverDrilldown - implements Drilldown { + implements Drilldown { constructor(protected readonly params: Params) {} public readonly id = SAMPLE_DASHBOARD_TO_DISCOVER_DRILLDOWN; diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/triggers/sample_app1_trigger.ts b/x-pack/examples/ui_actions_enhanced_examples/public/triggers/sample_app1_trigger.ts index 93a985626c6cd..aaec3f6b16ea5 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/public/triggers/sample_app1_trigger.ts +++ b/x-pack/examples/ui_actions_enhanced_examples/public/triggers/sample_app1_trigger.ts @@ -8,18 +8,12 @@ import { Trigger } from '../../../../../src/plugins/ui_actions/public'; export const SAMPLE_APP1_CLICK_TRIGGER = 'SAMPLE_APP1_CLICK_TRIGGER'; -export const sampleApp1ClickTrigger: Trigger<'SAMPLE_APP1_CLICK_TRIGGER'> = { +export const sampleApp1ClickTrigger: Trigger = { id: SAMPLE_APP1_CLICK_TRIGGER, title: 'App 1 trigger fired on click', description: 'Could be a click on a ML job in ML app.', }; -declare module '../../../../../src/plugins/ui_actions/public' { - export interface TriggerContextMapping { - [SAMPLE_APP1_CLICK_TRIGGER]: SampleApp1ClickContext; - } -} - export interface SampleApp1ClickContext { job: SampleMlJob; } diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/triggers/sample_app2_trigger.ts b/x-pack/examples/ui_actions_enhanced_examples/public/triggers/sample_app2_trigger.ts index 664c99afc94a5..f8e214cf7d440 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/public/triggers/sample_app2_trigger.ts +++ b/x-pack/examples/ui_actions_enhanced_examples/public/triggers/sample_app2_trigger.ts @@ -8,18 +8,12 @@ import { Trigger } from '../../../../../src/plugins/ui_actions/public'; export const SAMPLE_APP2_CLICK_TRIGGER = 'SAMPLE_APP2_CLICK_TRIGGER'; -export const sampleApp2ClickTrigger: Trigger<'SAMPLE_APP2_CLICK_TRIGGER'> = { +export const sampleApp2ClickTrigger: Trigger = { id: SAMPLE_APP2_CLICK_TRIGGER, title: 'App 2 trigger fired on click', description: 'Could be a click on an element in Canvas app.', }; -declare module '../../../../../src/plugins/ui_actions/public' { - export interface TriggerContextMapping { - [SAMPLE_APP2_CLICK_TRIGGER]: SampleApp2ClickContext; - } -} - export interface SampleApp2ClickContext { workpadId: string; elementId: string; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx index 451254efd9648..66f64fe95ff53 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/abstract_dashboard_drilldown.tsx @@ -8,10 +8,6 @@ import React from 'react'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { DashboardStart } from 'src/plugins/dashboard/public'; import { reactToUiComponent } from '../../../../../../../src/plugins/kibana_react/public'; -import { - TriggerContextMapping, - TriggerId, -} from '../../../../../../../src/plugins/ui_actions/public'; import { CollectConfigContainer } from './components'; import { AdvancedUiActionsStart, @@ -34,15 +30,15 @@ export interface Params { }>; } -export abstract class AbstractDashboardDrilldown - implements Drilldown> { +export abstract class AbstractDashboardDrilldown + implements Drilldown { constructor(protected readonly params: Params) {} public abstract readonly id: string; - public abstract readonly supportedTriggers: () => T[]; + public abstract readonly supportedTriggers: () => string[]; - protected abstract getURL(config: Config, context: TriggerContextMapping[T]): Promise; + protected abstract getURL(config: Config, context: Context): Promise; public readonly order = 100; @@ -51,7 +47,7 @@ export abstract class AbstractDashboardDrilldown public readonly euiIcon = 'dashboardApp'; private readonly ReactCollectConfig: React.FC< - CollectConfigProps> + CollectConfigProps > = (props) => ; public readonly CollectConfig = reactToUiComponent(this.ReactCollectConfig); @@ -67,15 +63,12 @@ export abstract class AbstractDashboardDrilldown return true; }; - public readonly getHref = async ( - config: Config, - context: TriggerContextMapping[T] - ): Promise => { + public readonly getHref = async (config: Config, context: Context): Promise => { const url = await this.getURL(config, context); return url.path; }; - public readonly execute = async (config: Config, context: TriggerContextMapping[T]) => { + public readonly execute = async (config: Config, context: Context) => { const url = await this.getURL(config, context); await this.params.start().core.application.navigateToApp(url.appName, { path: url.appPath }); }; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts index d2d3c37a69287..04256362da4a8 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/abstract_dashboard_drilldown/types.ts @@ -5,9 +5,8 @@ */ import { UiActionsEnhancedBaseActionFactoryContext } from '../../../../../ui_actions_enhanced/public'; -import { APPLY_FILTER_TRIGGER } from '../../../../../../../src/plugins/data/public'; import { DrilldownConfig } from '../../../../common'; export type Config = DrilldownConfig; -export type FactoryContext = UiActionsEnhancedBaseActionFactoryContext; +export type FactoryContext = UiActionsEnhancedBaseActionFactoryContext; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/drilldown_shared.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/drilldown_shared.ts index ff79cda1bb215..5c959432011f2 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/drilldown_shared.ts +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/drilldown_shared.ts @@ -9,7 +9,6 @@ import { SELECT_RANGE_TRIGGER, VALUE_CLICK_TRIGGER, } from '../../../../../../../src/plugins/embeddable/public'; -import { TriggerId } from '../../../../../../../src/plugins/ui_actions/public'; /** * We know that VALUE_CLICK_TRIGGER and SELECT_RANGE_TRIGGER are also triggering APPLY_FILTER_TRIGGER. @@ -21,7 +20,7 @@ import { TriggerId } from '../../../../../../../src/plugins/ui_actions/public'; * * @param triggers */ -export function ensureNestedTriggers(triggers: TriggerId[]): TriggerId[] { +export function ensureNestedTriggers(triggers: string[]): string[] { if ( !triggers.includes(APPLY_FILTER_TRIGGER) && (triggers.includes(VALUE_CLICK_TRIGGER) || triggers.includes(SELECT_RANGE_TRIGGER)) diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.test.tsx index ff54e0812975d..02b086fb301c8 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.test.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.test.tsx @@ -10,10 +10,6 @@ import { } from './flyout_create_drilldown'; import { coreMock } from '../../../../../../../../src/core/public/mocks'; import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { - TriggerContextMapping, - TriggerId, -} from '../../../../../../../../src/plugins/ui_actions/public'; import { MockEmbeddable, enhanceEmbeddable } from '../test_helpers'; import { uiActionsEnhancedPluginMock } from '../../../../../../ui_actions_enhanced/public/mocks'; import { UiActionsEnhancedActionFactory } from '../../../../../../ui_actions_enhanced/public/'; @@ -54,7 +50,7 @@ interface CompatibilityParams { isValueClickTriggerSupported?: boolean; isEmbeddableEnhanced?: boolean; rootType?: string; - actionFactoriesTriggers?: TriggerId[]; + actionFactoriesTriggers?: string[]; } describe('isCompatible', () => { @@ -79,9 +75,7 @@ describe('isCompatible', () => { let embeddable = new MockEmbeddable( { id: '', viewMode: isEdit ? ViewMode.EDIT : ViewMode.VIEW }, { - supportedTriggers: (isValueClickTriggerSupported ? ['VALUE_CLICK_TRIGGER'] : []) as Array< - keyof TriggerContextMapping - >, + supportedTriggers: isValueClickTriggerSupported ? ['VALUE_CLICK_TRIGGER'] : [], } ); diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.tsx index a417deb47db53..12aa2f8250e24 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { ActionByType } from '../../../../../../../../src/plugins/ui_actions/public'; +import { Action } from '../../../../../../../../src/plugins/ui_actions/public'; import { toMountPoint } from '../../../../../../../../src/plugins/kibana_react/public'; import { isEnhancedEmbeddable, @@ -26,7 +26,7 @@ export interface OpenFlyoutAddDrilldownParams { start: StartServicesGetter>; } -export class FlyoutCreateDrilldownAction implements ActionByType { +export class FlyoutCreateDrilldownAction implements Action { public readonly type = OPEN_FLYOUT_ADD_DRILLDOWN; public readonly id = OPEN_FLYOUT_ADD_DRILLDOWN; public order = 12; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.tsx index 1f0570445a8fc..10d82707d0817 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; -import { ActionByType } from '../../../../../../../../src/plugins/ui_actions/public'; +import { Action } from '../../../../../../../../src/plugins/ui_actions/public'; import { reactToUiComponent, toMountPoint, @@ -31,7 +31,7 @@ export interface FlyoutEditDrilldownParams { start: StartServicesGetter>; } -export class FlyoutEditDrilldownAction implements ActionByType { +export class FlyoutEditDrilldownAction implements Action { public readonly type = OPEN_FLYOUT_EDIT_DRILLDOWN; public readonly id = OPEN_FLYOUT_EDIT_DRILLDOWN; public order = 10; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx index 27a8d73f32944..6f000756601ea 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx @@ -21,6 +21,7 @@ test('', () => { dynamicActions: ({ state } as unknown) as DynamicActionManager, }, } as unknown) as EnhancedEmbeddable, + trigger: {} as any, }} /> ); diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.tsx index 5a04e03e03457..f834d925a6494 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.tsx @@ -9,8 +9,11 @@ import { EuiNotificationBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { useContainerState } from '../../../../../../../../src/plugins/kibana_utils/public'; import { EnhancedEmbeddableContext } from '../../../../../../embeddable_enhanced/public'; import { txtDisplayName } from './i18n'; +import { ActionExecutionContext } from '../../../../../../../../src/plugins/ui_actions/public'; -export const MenuItem: React.FC<{ context: EnhancedEmbeddableContext }> = ({ context }) => { +export const MenuItem: React.FC<{ context: ActionExecutionContext }> = ({ + context, +}) => { const { events } = useContainerState(context.embeddable.enhancements.dynamicActions.state); const count = events.length; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts index e831f87baa11c..432ee6d3070ad 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts @@ -11,23 +11,19 @@ import { UiActionsEnhancedDynamicActionManager as DynamicActionManager, AdvancedUiActionsStart, } from '../../../../../ui_actions_enhanced/public'; -import { TriggerContextMapping } from '../../../../../../../src/plugins/ui_actions/public'; import { uiActionsEnhancedPluginMock } from '../../../../../ui_actions_enhanced/public/mocks'; export class MockEmbeddable extends Embeddable { public rootType = 'dashboard'; public readonly type = 'mock'; - private readonly triggers: Array = []; - constructor( - initialInput: EmbeddableInput, - params: { supportedTriggers?: Array } - ) { + private readonly triggers: string[] = []; + constructor(initialInput: EmbeddableInput, params: { supportedTriggers?: string[] }) { super(initialInput, {}, undefined); this.triggers = params.supportedTriggers ?? []; } public render(node: HTMLElement) {} public reload() {} - public supportedTriggers(): Array { + public supportedTriggers(): string[] { return this.triggers; } public getRoot() { diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts index e1b6493be5200..d43a50775148d 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts @@ -7,23 +7,10 @@ import { CoreSetup } from 'src/core/public'; import { SetupDependencies, StartDependencies } from '../../plugin'; import { CONTEXT_MENU_TRIGGER } from '../../../../../../src/plugins/embeddable/public'; -import { EnhancedEmbeddableContext } from '../../../../embeddable_enhanced/public'; -import { - FlyoutCreateDrilldownAction, - FlyoutEditDrilldownAction, - OPEN_FLYOUT_ADD_DRILLDOWN, - OPEN_FLYOUT_EDIT_DRILLDOWN, -} from './actions'; +import { FlyoutCreateDrilldownAction, FlyoutEditDrilldownAction } from './actions'; import { EmbeddableToDashboardDrilldown } from './embeddable_to_dashboard_drilldown'; import { createStartServicesGetter } from '../../../../../../src/plugins/kibana_utils/public'; -declare module '../../../../../../src/plugins/ui_actions/public' { - export interface ActionContextMapping { - [OPEN_FLYOUT_ADD_DRILLDOWN]: EnhancedEmbeddableContext; - [OPEN_FLYOUT_EDIT_DRILLDOWN]: EnhancedEmbeddableContext; - } -} - interface BootstrapParams { enableDrilldowns: boolean; } diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.test.tsx index 5bfb175ea0d00..c33b26b42cb32 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.test.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.test.tsx @@ -23,6 +23,7 @@ import { UrlGeneratorsService } from '../../../../../../../src/plugins/share/pub import { StartDependencies } from '../../../plugin'; import { SavedObjectLoader } from '../../../../../../../src/plugins/saved_objects/public'; import { StartServicesGetter } from '../../../../../../../src/plugins/kibana_utils/public/core'; +import { EnhancedEmbeddableContext } from '../../../../../embeddable_enhanced/public'; describe('.isConfigValid()', () => { const drilldown = new EmbeddableToDashboardDrilldown({} as any); @@ -140,7 +141,7 @@ describe('.execute() & getHref', () => { }), }, timeFieldName, - } as unknown) as ApplyGlobalFilterActionContext; + } as unknown) as ApplyGlobalFilterActionContext & EnhancedEmbeddableContext; await drilldown.execute(completeConfig, context); diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx index c2bf48188c313..0bd21a82af54b 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { TriggerContextMapping } from '../../../../../../../src/plugins/ui_actions/public'; import { DashboardUrlGeneratorState } from '../../../../../../../src/plugins/dashboard/public'; import { + ApplyGlobalFilterActionContext, APPLY_FILTER_TRIGGER, esFilters, Filter, @@ -25,6 +25,7 @@ import { import { KibanaURL } from '../../../../../../../src/plugins/share/public'; import { EMBEDDABLE_TO_DASHBOARD_DRILLDOWN } from './constants'; import { createExtract, createInject } from '../../../../common'; +import { EnhancedEmbeddableContext } from '../../../../../embeddable_enhanced/public'; interface EmbeddableQueryInput extends EmbeddableInput { query?: Query; @@ -32,8 +33,7 @@ interface EmbeddableQueryInput extends EmbeddableInput { timeRange?: TimeRange; } -type Trigger = typeof APPLY_FILTER_TRIGGER; -type Context = TriggerContextMapping[Trigger]; +type Context = EnhancedEmbeddableContext & ApplyGlobalFilterActionContext; export type Params = AbstractDashboardDrilldownParams; /** @@ -43,10 +43,10 @@ export type Params = AbstractDashboardDrilldownParams; * by embeddables (but not necessarily); (2) its `getURL` method depends on * `embeddable` field being present in `context`. */ -export class EmbeddableToDashboardDrilldown extends AbstractDashboardDrilldown { +export class EmbeddableToDashboardDrilldown extends AbstractDashboardDrilldown { public readonly id = EMBEDDABLE_TO_DASHBOARD_DRILLDOWN; - public readonly supportedTriggers = () => [APPLY_FILTER_TRIGGER] as Trigger[]; + public readonly supportedTriggers = () => [APPLY_FILTER_TRIGGER]; protected async getURL(config: Config, context: Context): Promise { const state: DashboardUrlGeneratorState = { diff --git a/x-pack/plugins/discover_enhanced/public/index.ts b/x-pack/plugins/discover_enhanced/public/index.ts index 943a212dd7c4e..c44815707b9be 100644 --- a/x-pack/plugins/discover_enhanced/public/index.ts +++ b/x-pack/plugins/discover_enhanced/public/index.ts @@ -4,10 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PluginInitializerContext } from 'kibana/public'; +import type { PluginInitializerContext } from 'kibana/public'; import { DiscoverEnhancedPlugin } from './plugin'; -export { +export type { ExploreDataContextMenuAction, ExploreDataChartAction } from './actions'; + +export type { DiscoverEnhancedPlugin, DiscoverEnhancedSetupDependencies, DiscoverEnhancedStartDependencies, diff --git a/x-pack/plugins/discover_enhanced/public/plugin.ts b/x-pack/plugins/discover_enhanced/public/plugin.ts index 78f3464484ccf..7f6f83fba16f6 100644 --- a/x-pack/plugins/discover_enhanced/public/plugin.ts +++ b/x-pack/plugins/discover_enhanced/public/plugin.ts @@ -15,25 +15,11 @@ import { KibanaLegacySetup, KibanaLegacyStart } from '../../../../src/plugins/ki import { EmbeddableSetup, EmbeddableStart, - EmbeddableContext, CONTEXT_MENU_TRIGGER, } from '../../../../src/plugins/embeddable/public'; -import { - ExploreDataContextMenuAction, - ExploreDataChartAction, - ACTION_EXPLORE_DATA, - ACTION_EXPLORE_DATA_CHART, - ExploreDataChartActionContext, -} from './actions'; +import { ExploreDataContextMenuAction, ExploreDataChartAction } from './actions'; import { Config } from '../common'; -declare module '../../../../src/plugins/ui_actions/public' { - export interface ActionContextMapping { - [ACTION_EXPLORE_DATA]: EmbeddableContext; - [ACTION_EXPLORE_DATA_CHART]: ExploreDataChartActionContext; - } -} - export interface DiscoverEnhancedSetupDependencies { discover: DiscoverSetup; embeddable: EmbeddableSetup; diff --git a/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx b/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx index ffb0687305168..3587e472324c6 100644 --- a/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx +++ b/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx @@ -56,14 +56,14 @@ export type UrlTrigger = | typeof ROW_CLICK_TRIGGER | typeof CONTEXT_MENU_TRIGGER; -export interface ActionFactoryContext extends BaseActionFactoryContext { +export interface ActionFactoryContext extends BaseActionFactoryContext { embeddable?: EmbeddableWithQueryInput; } export type CollectConfigProps = CollectConfigPropsBase; const URL_DRILLDOWN = 'URL_DRILLDOWN'; -export class UrlDrilldown implements Drilldown { +export class UrlDrilldown implements Drilldown { public readonly id = URL_DRILLDOWN; constructor(private readonly deps: UrlDrilldownDeps) {} diff --git a/x-pack/plugins/embeddable_enhanced/public/plugin.ts b/x-pack/plugins/embeddable_enhanced/public/plugin.ts index 5d5ad852839d4..a901584080dce 100644 --- a/x-pack/plugins/embeddable_enhanced/public/plugin.ts +++ b/x-pack/plugins/embeddable_enhanced/public/plugin.ts @@ -19,7 +19,7 @@ import { PANEL_NOTIFICATION_TRIGGER, ViewMode, } from '../../../../src/plugins/embeddable/public'; -import { EnhancedEmbeddable, EnhancedEmbeddableContext } from './types'; +import { EnhancedEmbeddable } from './types'; import { EmbeddableActionStorage, EmbeddableWithDynamicActions, @@ -29,13 +29,7 @@ import { AdvancedUiActionsSetup, AdvancedUiActionsStart, } from '../../ui_actions_enhanced/public'; -import { PanelNotificationsAction, ACTION_PANEL_NOTIFICATIONS } from './actions'; - -declare module '../../../../src/plugins/ui_actions/public' { - export interface ActionContextMapping { - [ACTION_PANEL_NOTIFICATIONS]: EnhancedEmbeddableContext; - } -} +import { PanelNotificationsAction } from './actions'; export interface SetupDependencies { embeddable: EmbeddableSetup; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx index deb48027512cc..6411b0e5f1ad9 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx @@ -34,7 +34,7 @@ import { IFieldType, IIndexPattern, } from '../../../../../../../src/plugins/data/public'; -import { TriggerId, UiActionsStart } from '../../../../../../../src/plugins/ui_actions/public'; +import { UiActionsStart } from '../../../../../../../src/plugins/ui_actions/public'; import { uiActionsPluginMock } from '../../../../../../../src/plugins/ui_actions/public/mocks'; import { TriggerContract } from '../../../../../../../src/plugins/ui_actions/public/triggers'; import { VIS_EVENT_TO_TRIGGER } from '../../../../../../../src/plugins/visualizations/public/embeddable'; @@ -48,12 +48,12 @@ describe('workspace_panel', () => { let expressionRendererMock: jest.Mock; let uiActionsMock: jest.Mocked; let dataMock: jest.Mocked; - let trigger: jest.Mocked>; + let trigger: jest.Mocked; let instance: ReactWrapper; beforeEach(() => { - trigger = ({ exec: jest.fn() } as unknown) as jest.Mocked>; + trigger = ({ exec: jest.fn() } as unknown) as jest.Mocked; uiActionsMock = uiActionsPluginMock.createStartContract(); dataMock = dataPluginMock.createStartContract(); uiActionsMock.getTrigger.mockReturnValue(trigger); diff --git a/x-pack/plugins/lens/public/trigger_actions/visualize_field_actions.ts b/x-pack/plugins/lens/public/trigger_actions/visualize_field_actions.ts index a473d433ac89d..caf22088daf96 100644 --- a/x-pack/plugins/lens/public/trigger_actions/visualize_field_actions.ts +++ b/x-pack/plugins/lens/public/trigger_actions/visualize_field_actions.ts @@ -12,7 +12,7 @@ import { import { ApplicationStart } from '../../../../../src/core/public'; export const visualizeFieldAction = (application: ApplicationStart) => - createAction({ + createAction({ type: ACTION_VISUALIZE_LENS_FIELD, id: ACTION_VISUALIZE_LENS_FIELD, getDisplayName: () => diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts index a5e17a05cf71d..8a90e24a5dbe5 100644 --- a/x-pack/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -8,7 +8,7 @@ import { IconType } from '@elastic/eui/src/components/icon/icon'; import { CoreSetup } from 'kibana/public'; import { PaletteOutput, PaletteRegistry } from 'src/plugins/charts/public'; import { SavedObjectReference } from 'kibana/public'; -import { ROW_CLICK_TRIGGER } from '../../../../src/plugins/ui_actions/public'; +import { RowClickContext } from '../../../../src/plugins/ui_actions/public'; import { ExpressionAstExpression, ExpressionRendererEvent, @@ -20,11 +20,8 @@ import { DragContextState } from './drag_drop'; import { Document } from './persistence'; import { DateRange } from '../common'; import { Query, Filter, SavedQuery, IFieldFormat } from '../../../../src/plugins/data/public'; -import { TriggerContext, VisualizeFieldContext } from '../../../../src/plugins/ui_actions/public'; -import { - SELECT_RANGE_TRIGGER, - VALUE_CLICK_TRIGGER, -} from '../../../../src/plugins/embeddable/public'; +import { VisualizeFieldContext } from '../../../../src/plugins/ui_actions/public'; +import { RangeSelectContext, ValueClickContext } from '../../../../src/plugins/embeddable/public'; import type { LensSortActionData, LENS_EDIT_SORT_ACTION, @@ -623,12 +620,12 @@ export interface Visualization { export interface LensFilterEvent { name: 'filter'; - data: TriggerContext['data']; + data: ValueClickContext['data']; } export interface LensBrushEvent { name: 'brush'; - data: TriggerContext['data']; + data: RangeSelectContext['data']; } // Use same technique as TriggerContext @@ -649,7 +646,7 @@ export interface LensEditEvent { } export interface LensTableRowContextMenuEvent { name: 'tableRowContextMenuClick'; - data: TriggerContext['data']; + data: RowClickContext['data']; } export function isLensFilterEvent(event: ExpressionRendererEvent): event is LensFilterEvent { diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx index 5e5d431c7c212..1848f841c771b 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx @@ -16,10 +16,7 @@ import { ReferenceOrValueEmbeddable, VALUE_CLICK_TRIGGER, } from '../../../../../src/plugins/embeddable/public'; -import { - ActionExecutionContext, - TriggerContextMapping, -} from '../../../../../src/plugins/ui_actions/public'; +import { ActionExecutionContext } from '../../../../../src/plugins/ui_actions/public'; import { ACTION_GLOBAL_APPLY_FILTER, APPLY_FILTER_TRIGGER, @@ -204,7 +201,7 @@ export class MapEmbeddable return this._isInitialized ? this._savedMap.getAttributes().description : ''; } - public supportedTriggers(): Array { + public supportedTriggers(): string[] { return [APPLY_FILTER_TRIGGER, VALUE_CLICK_TRIGGER]; } diff --git a/x-pack/plugins/maps/public/trigger_actions/trigger_utils.ts b/x-pack/plugins/maps/public/trigger_actions/trigger_utils.ts index 3505588a9c049..5b530173f9e26 100644 --- a/x-pack/plugins/maps/public/trigger_actions/trigger_utils.ts +++ b/x-pack/plugins/maps/public/trigger_actions/trigger_utils.ts @@ -9,7 +9,6 @@ import { RawValue } from '../../common/constants'; import { DatatableColumnType } from '../../../../../src/plugins/expressions'; export function isUrlDrilldown(action: Action) { - // @ts-expect-error return action.type === 'URL_DRILLDOWN'; } diff --git a/x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts b/x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts index bdeab292b214c..fdfca4877428c 100644 --- a/x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts +++ b/x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts @@ -21,7 +21,8 @@ import { import { MAPS_APP_URL_GENERATOR, MapsUrlGeneratorState } from '../url_generator'; import { LAYER_TYPE, SOURCE_TYPES, SCALING_TYPES, APP_ID, MAP_PATH } from '../../common/constants'; -export const visualizeGeoFieldAction = createAction({ +export const visualizeGeoFieldAction = createAction({ + id: ACTION_VISUALIZE_GEO_FIELD, type: ACTION_VISUALIZE_GEO_FIELD, getDisplayName: () => i18n.translate('xpack.maps.discover.visualizeFieldLabel', { diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/embeddable_swim_lane_container.test.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/embeddable_swim_lane_container.test.tsx index ff621953cc577..b4740ea9333f6 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/embeddable_swim_lane_container.test.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_swimlane/embeddable_swim_lane_container.test.tsx @@ -20,7 +20,6 @@ import { SwimlaneContainer } from '../../application/explorer/swimlane_container import { MlDependencies } from '../../application/app'; import { uiActionsPluginMock } from 'src/plugins/ui_actions/public/mocks'; import { TriggerContract } from 'src/plugins/ui_actions/public/triggers'; -import { TriggerId } from 'src/plugins/ui_actions/public'; import { AnomalySwimlaneEmbeddableInput, AnomalySwimlaneServices } from '..'; jest.mock('./swimlane_input_resolver', () => ({ @@ -43,7 +42,7 @@ describe('ExplorerSwimlaneContainer', () => { let refresh: BehaviorSubject; let services: jest.Mocked<[CoreStart, MlDependencies, AnomalySwimlaneServices]>; let embeddableContext: AnomalySwimlaneEmbeddable; - let trigger: jest.Mocked>; + let trigger: jest.Mocked; const onInputChange = jest.fn(); const onOutputChange = jest.fn(); @@ -54,7 +53,7 @@ describe('ExplorerSwimlaneContainer', () => { id: 'test-swimlane-embeddable', } as Partial); - trigger = ({ exec: jest.fn() } as unknown) as jest.Mocked>; + trigger = ({ exec: jest.fn() } as unknown) as jest.Mocked; const uiActionsMock = uiActionsPluginMock.createStartContract(); uiActionsMock.getTrigger.mockReturnValue(trigger); diff --git a/x-pack/plugins/ml/public/ui_actions/apply_influencer_filters_action.tsx b/x-pack/plugins/ml/public/ui_actions/apply_influencer_filters_action.tsx index 50f00ac53edab..51784815bcc4b 100644 --- a/x-pack/plugins/ml/public/ui_actions/apply_influencer_filters_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/apply_influencer_filters_action.tsx @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { ActionContextMapping, createAction } from '../../../../../src/plugins/ui_actions/public'; +import { createAction } from '../../../../../src/plugins/ui_actions/public'; import { MlCoreSetup } from '../plugin'; import { SWIMLANE_TYPE, VIEW_BY_JOB_LABEL } from '../application/explorer/explorer_constants'; import { Filter, FilterStateStore } from '../../../../../src/plugins/data/common'; @@ -18,10 +18,10 @@ export const CONTROLLED_BY_SWIM_LANE_FILTER = 'anomaly-swim-lane'; export function createApplyInfluencerFiltersAction( getStartServices: MlCoreSetup['getStartServices'] ) { - return createAction({ + return createAction({ id: 'apply-to-current-view', type: APPLY_INFLUENCER_FILTERS_ACTION, - getIconType(context: ActionContextMapping[typeof APPLY_INFLUENCER_FILTERS_ACTION]): string { + getIconType(context: SwimLaneDrilldownContext): string { return 'filter'; }, getDisplayName() { @@ -29,7 +29,7 @@ export function createApplyInfluencerFiltersAction( defaultMessage: 'Filter for value', }); }, - async execute({ data }: SwimLaneDrilldownContext) { + async execute({ data }) { if (!data) { throw new Error('No swim lane selection data provided'); } @@ -67,7 +67,7 @@ export function createApplyInfluencerFiltersAction( }) ); }, - async isCompatible({ embeddable, data }: SwimLaneDrilldownContext) { + async isCompatible({ embeddable, data }) { // Only compatible with view by influencer swim lanes and single selection return ( embeddable.type === ANOMALY_SWIMLANE_EMBEDDABLE_TYPE && diff --git a/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx b/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx index 79e6ff53bff43..a92974772601d 100644 --- a/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/apply_time_range_action.tsx @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import moment from 'moment'; -import { ActionContextMapping, createAction } from '../../../../../src/plugins/ui_actions/public'; +import { createAction } from '../../../../../src/plugins/ui_actions/public'; import { MlCoreSetup } from '../plugin'; import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, SwimLaneDrilldownContext } from '../embeddables'; @@ -15,17 +15,17 @@ export const APPLY_TIME_RANGE_SELECTION_ACTION = 'applyTimeRangeSelectionAction' export function createApplyTimeRangeSelectionAction( getStartServices: MlCoreSetup['getStartServices'] ) { - return createAction({ + return createAction({ id: 'apply-time-range-selection', type: APPLY_TIME_RANGE_SELECTION_ACTION, - getIconType(context: ActionContextMapping[typeof APPLY_TIME_RANGE_SELECTION_ACTION]): string { + getIconType(context): string { return 'timeline'; }, getDisplayName: () => i18n.translate('xpack.ml.actions.applyTimeRangeSelectionTitle', { defaultMessage: 'Apply time range selection', }), - async execute({ embeddable, data }: SwimLaneDrilldownContext) { + async execute({ embeddable, data }) { if (!data) { throw new Error('No swim lane selection data provided'); } @@ -47,7 +47,7 @@ export function createApplyTimeRangeSelectionAction( mode: 'absolute', }); }, - async isCompatible({ embeddable, data }: SwimLaneDrilldownContext) { + async isCompatible({ embeddable, data }) { return embeddable.type === ANOMALY_SWIMLANE_EMBEDDABLE_TYPE && data !== undefined; }, }); diff --git a/x-pack/plugins/ml/public/ui_actions/clear_selection_action.tsx b/x-pack/plugins/ml/public/ui_actions/clear_selection_action.tsx index acafc787d05c2..46d71d61c361d 100644 --- a/x-pack/plugins/ml/public/ui_actions/clear_selection_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/clear_selection_action.tsx @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { ActionContextMapping, createAction } from '../../../../../src/plugins/ui_actions/public'; +import { createAction } from '../../../../../src/plugins/ui_actions/public'; import { MlCoreSetup } from '../plugin'; export const CLEAR_SELECTION_ACTION = 'clearSelectionAction'; @@ -15,10 +15,10 @@ export interface ClearSelectionContext { } export function createClearSelectionAction(getStartServices: MlCoreSetup['getStartServices']) { - return createAction({ + return createAction({ id: 'clear-selection-action', type: CLEAR_SELECTION_ACTION, - getIconType(context: ActionContextMapping[typeof CLEAR_SELECTION_ACTION]): string { + getIconType(context): string { return 'cross'; }, getDisplayName: () => @@ -26,10 +26,10 @@ export function createClearSelectionAction(getStartServices: MlCoreSetup['getSta defaultMessage: 'Clear selection', }), shouldAutoExecute: () => Promise.resolve(false), - async execute({ updateCallback }: ClearSelectionContext) { + async execute({ updateCallback }) { updateCallback(); }, - async isCompatible({ updateCallback }: ClearSelectionContext) { + async isCompatible({ updateCallback }) { return typeof updateCallback === 'function'; }, }); diff --git a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx index c40d1e175ec77..034f8be65af6f 100644 --- a/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/edit_swimlane_panel_action.tsx @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { ActionContextMapping, createAction } from '../../../../../src/plugins/ui_actions/public'; +import { createAction } from '../../../../../src/plugins/ui_actions/public'; import { ViewMode } from '../../../../../src/plugins/embeddable/public'; import { MlCoreSetup } from '../plugin'; import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, EditSwimlanePanelContext } from '../embeddables'; @@ -13,17 +13,17 @@ import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, EditSwimlanePanelContext } from '../e export const EDIT_SWIMLANE_PANEL_ACTION = 'editSwimlanePanelAction'; export function createEditSwimlanePanelAction(getStartServices: MlCoreSetup['getStartServices']) { - return createAction({ + return createAction({ id: 'edit-anomaly-swimlane', type: EDIT_SWIMLANE_PANEL_ACTION, - getIconType(context: ActionContextMapping[typeof EDIT_SWIMLANE_PANEL_ACTION]): string { + getIconType(context): string { return 'pencil'; }, getDisplayName: () => i18n.translate('xpack.ml.actions.editSwimlaneTitle', { defaultMessage: 'Edit swim lane', }), - async execute({ embeddable }: EditSwimlanePanelContext) { + async execute({ embeddable }) { if (!embeddable) { throw new Error('Not possible to execute an action without the embeddable context'); } @@ -41,7 +41,7 @@ export function createEditSwimlanePanelAction(getStartServices: MlCoreSetup['get return Promise.reject(); } }, - async isCompatible({ embeddable }: EditSwimlanePanelContext) { + async isCompatible({ embeddable }) { return ( embeddable.type === ANOMALY_SWIMLANE_EMBEDDABLE_TYPE && embeddable.getInput().viewMode === ViewMode.EDIT diff --git a/x-pack/plugins/ml/public/ui_actions/index.ts b/x-pack/plugins/ml/public/ui_actions/index.ts index 2b01a74070b22..8d515027a2ff4 100644 --- a/x-pack/plugins/ml/public/ui_actions/index.ts +++ b/x-pack/plugins/ml/public/ui_actions/index.ts @@ -5,32 +5,15 @@ */ import { CoreSetup } from 'kibana/public'; -import { - createEditSwimlanePanelAction, - EDIT_SWIMLANE_PANEL_ACTION, -} from './edit_swimlane_panel_action'; -import { - createOpenInExplorerAction, - OPEN_IN_ANOMALY_EXPLORER_ACTION, -} from './open_in_anomaly_explorer_action'; +import { createEditSwimlanePanelAction } from './edit_swimlane_panel_action'; +import { createOpenInExplorerAction } from './open_in_anomaly_explorer_action'; import { UiActionsSetup } from '../../../../../src/plugins/ui_actions/public'; import { MlPluginStart, MlStartDependencies } from '../plugin'; import { CONTEXT_MENU_TRIGGER } from '../../../../../src/plugins/embeddable/public'; -import { - APPLY_INFLUENCER_FILTERS_ACTION, - createApplyInfluencerFiltersAction, -} from './apply_influencer_filters_action'; +import { createApplyInfluencerFiltersAction } from './apply_influencer_filters_action'; import { SWIM_LANE_SELECTION_TRIGGER, swimLaneSelectionTrigger } from './triggers'; -import { - APPLY_TIME_RANGE_SELECTION_ACTION, - createApplyTimeRangeSelectionAction, -} from './apply_time_range_action'; -import { EditSwimlanePanelContext, SwimLaneDrilldownContext } from '../embeddables'; -import { - CLEAR_SELECTION_ACTION, - ClearSelectionContext, - createClearSelectionAction, -} from './clear_selection_action'; +import { createApplyTimeRangeSelectionAction } from './apply_time_range_action'; +import { createClearSelectionAction } from './clear_selection_action'; export { APPLY_TIME_RANGE_SELECTION_ACTION } from './apply_time_range_action'; export { EDIT_SWIMLANE_PANEL_ACTION } from './edit_swimlane_panel_action'; @@ -71,17 +54,3 @@ export function registerMlUiActions( uiActions.addTriggerAction(SWIM_LANE_SELECTION_TRIGGER, openInExplorerAction); uiActions.addTriggerAction(SWIM_LANE_SELECTION_TRIGGER, clearSelectionAction); } - -declare module '../../../../../src/plugins/ui_actions/public' { - export interface ActionContextMapping { - [EDIT_SWIMLANE_PANEL_ACTION]: EditSwimlanePanelContext; - [OPEN_IN_ANOMALY_EXPLORER_ACTION]: SwimLaneDrilldownContext; - [APPLY_INFLUENCER_FILTERS_ACTION]: SwimLaneDrilldownContext; - [APPLY_TIME_RANGE_SELECTION_ACTION]: SwimLaneDrilldownContext; - [CLEAR_SELECTION_ACTION]: ClearSelectionContext; - } - - export interface TriggerContextMapping { - [SWIM_LANE_SELECTION_TRIGGER]: SwimLaneDrilldownContext | ClearSelectionContext; - } -} diff --git a/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx b/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx index e4d7cfa32c2cd..da0c43f231f8a 100644 --- a/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { ActionContextMapping, createAction } from '../../../../../src/plugins/ui_actions/public'; +import { createAction } from '../../../../../src/plugins/ui_actions/public'; import { MlCoreSetup } from '../plugin'; import { ML_APP_URL_GENERATOR } from '../../common/constants/ml_url_generator'; import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, SwimLaneDrilldownContext } from '../embeddables'; @@ -13,10 +13,10 @@ import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, SwimLaneDrilldownContext } from '../e export const OPEN_IN_ANOMALY_EXPLORER_ACTION = 'openInAnomalyExplorerAction'; export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getStartServices']) { - return createAction({ + return createAction({ id: 'open-in-anomaly-explorer', type: OPEN_IN_ANOMALY_EXPLORER_ACTION, - getIconType(context: ActionContextMapping[typeof OPEN_IN_ANOMALY_EXPLORER_ACTION]): string { + getIconType(context): string { return 'visTable'; }, getDisplayName() { @@ -24,7 +24,7 @@ export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getSta defaultMessage: 'Open in Anomaly Explorer', }); }, - async getHref({ embeddable, data }: SwimLaneDrilldownContext): Promise { + async getHref({ embeddable, data }): Promise { const [, pluginsStart] = await getStartServices(); const urlGenerator = pluginsStart.share.urlGenerators.getUrlGenerator(ML_APP_URL_GENERATOR); const { jobIds, timeRange, viewBy } = embeddable.getInput(); @@ -50,7 +50,7 @@ export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getSta }, }); }, - async execute({ embeddable, data }: SwimLaneDrilldownContext) { + async execute({ embeddable, data }) { if (!embeddable) { throw new Error('Not possible to execute an action without the embeddable context'); } diff --git a/x-pack/plugins/ml/public/ui_actions/triggers.ts b/x-pack/plugins/ml/public/ui_actions/triggers.ts index 8a8b2602573a1..9db7536d7d5ba 100644 --- a/x-pack/plugins/ml/public/ui_actions/triggers.ts +++ b/x-pack/plugins/ml/public/ui_actions/triggers.ts @@ -8,7 +8,7 @@ import { Trigger } from '../../../../../src/plugins/ui_actions/public'; export const SWIM_LANE_SELECTION_TRIGGER = 'SWIM_LANE_SELECTION_TRIGGER'; -export const swimLaneSelectionTrigger: Trigger<'SWIM_LANE_SELECTION_TRIGGER'> = { +export const swimLaneSelectionTrigger: Trigger = { id: SWIM_LANE_SELECTION_TRIGGER, // This is empty string to hide title of ui_actions context menu that appears // when this trigger is executed. diff --git a/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/action_wizard.tsx b/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/action_wizard.tsx index 7a705f03c0650..519d4ffb50ba6 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/action_wizard.tsx +++ b/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/action_wizard.tsx @@ -32,7 +32,7 @@ import { } from './i18n'; import './action_wizard.scss'; import { ActionFactory, BaseActionConfig, BaseActionFactoryContext } from '../../dynamic_actions'; -import { Trigger, TriggerId } from '../../../../../../src/plugins/ui_actions/public'; +import { Trigger } from '../../../../../../src/plugins/ui_actions/public'; export interface ActionWizardProps< ActionFactoryContext extends BaseActionFactoryContext = BaseActionFactoryContext @@ -73,14 +73,14 @@ export interface ActionWizardProps< * Trigger selection has changed * @param triggers */ - onSelectedTriggersChange: (triggers?: TriggerId[]) => void; + onSelectedTriggersChange: (triggers?: string[]) => void; - getTriggerInfo: (triggerId: TriggerId) => Trigger; + getTriggerInfo: (triggerId: string) => Trigger; /** * List of possible triggers in current context */ - triggers: TriggerId[]; + triggers: string[]; triggerPickerDocsLink?: string; } @@ -148,10 +148,10 @@ export const ActionWizard: React.FC = ({ }; interface TriggerPickerProps { - triggers: TriggerId[]; - selectedTriggers?: TriggerId[]; - getTriggerInfo: (triggerId: TriggerId) => Trigger; - onSelectedTriggersChange: (triggers?: TriggerId[]) => void; + triggers: string[]; + selectedTriggers?: string[]; + getTriggerInfo: (triggerId: string) => Trigger; + onSelectedTriggersChange: (triggers?: string[]) => void; triggerPickerDocsLink?: string; } @@ -224,9 +224,9 @@ interface SelectedActionFactoryProps< onConfigChange: (config: BaseActionConfig) => void; showDeselect: boolean; onDeselect: () => void; - allTriggers: TriggerId[]; - getTriggerInfo: (triggerId: TriggerId) => Trigger; - onSelectedTriggersChange: (triggers?: TriggerId[]) => void; + allTriggers: string[]; + getTriggerInfo: (triggerId: string) => Trigger; + onSelectedTriggersChange: (triggers?: string[]) => void; triggerPickerDocsLink?: string; } @@ -379,7 +379,7 @@ const ActionFactorySelector: React.FC = ({ function getTriggersForActionFactory( actionFactory: ActionFactory, - allTriggers: TriggerId[] -): TriggerId[] { + allTriggers: string[] +): string[] { return actionFactory.supportedTriggers().filter((trigger) => allTriggers.includes(trigger)); } diff --git a/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/test_data.tsx b/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/test_data.tsx index 77362752f6960..e3dd070a5d42e 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/test_data.tsx +++ b/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/test_data.tsx @@ -11,7 +11,7 @@ import { ActionWizard } from './action_wizard'; import { ActionFactory, ActionFactoryDefinition, BaseActionConfig } from '../../dynamic_actions'; import { CollectConfigProps } from '../../../../../../src/plugins/kibana_utils/public'; import { licensingMock } from '../../../../licensing/public/mocks'; -import { Trigger, TriggerId } from '../../../../../../src/plugins/ui_actions/public'; +import { Trigger } from '../../../../../../src/plugins/ui_actions/public'; import { APPLY_FILTER_TRIGGER } from '../../../../../../src/plugins/data/public'; import { SELECT_RANGE_TRIGGER, @@ -80,7 +80,6 @@ function DashboardDrilldownCollectConfig(props: CollectConfigProps = { id: 'Dashboard', @@ -184,12 +183,12 @@ export const mockActionFactories: ActionFactory[] = ([dashboardFactory, urlFacto ActionFactory >) as ActionFactory[]; -export const mockSupportedTriggers: TriggerId[] = [ +export const mockSupportedTriggers: string[] = [ VALUE_CLICK_TRIGGER, SELECT_RANGE_TRIGGER, APPLY_FILTER_TRIGGER, ]; -export const mockGetTriggerInfo = (triggerId: TriggerId): Trigger => { +export const mockGetTriggerInfo = (triggerId: string): Trigger => { const titleMap = { [VALUE_CLICK_TRIGGER]: 'Single click', [SELECT_RANGE_TRIGGER]: 'Range selection', @@ -213,7 +212,7 @@ export function Demo({ actionFactories }: { actionFactories: Array({}); function changeActionFactory(newActionFactory?: ActionFactory) { diff --git a/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.tsx b/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.tsx index 259fe5c774c4b..eb6259f10896c 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.tsx +++ b/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.tsx @@ -7,10 +7,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { IEmbeddable, Embeddable, EmbeddableInput } from 'src/plugins/embeddable/public'; -import { - ActionDefinitionByType, - IncompatibleActionError, -} from '../../../../src/plugins/ui_actions/public'; +import { Action, IncompatibleActionError } from '../../../../src/plugins/ui_actions/public'; import { TimeRange } from '../../../../src/plugins/data/public'; import { CustomizeTimeRangeModal } from './customize_time_range_modal'; import { OpenModal, CommonlyUsedRange } from './types'; @@ -41,7 +38,7 @@ export interface TimeRangeActionContext { embeddable: Embeddable; } -export class CustomTimeRangeAction implements ActionDefinitionByType { +export class CustomTimeRangeAction implements Action { public readonly type = CUSTOM_TIME_RANGE; private openModal: OpenModal; private dateFormat?: string; diff --git a/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_badge.tsx b/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_badge.tsx index 28d99db9b3ef7..764fe520223bf 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_badge.tsx +++ b/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_badge.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { prettyDuration, commonDurationRanges } from '@elastic/eui'; import { IEmbeddable, Embeddable, EmbeddableInput } from 'src/plugins/embeddable/public'; -import { ActionByType, IncompatibleActionError } from '../../../../src/plugins/ui_actions/public'; +import { Action, IncompatibleActionError } from '../../../../src/plugins/ui_actions/public'; import { TimeRange } from '../../../../src/plugins/data/public'; import { CustomizeTimeRangeModal } from './customize_time_range_modal'; import { doesInheritTimeRange } from './does_inherit_time_range'; @@ -29,7 +29,7 @@ export interface TimeBadgeActionContext { embeddable: Embeddable; } -export class CustomTimeRangeBadge implements ActionByType { +export class CustomTimeRangeBadge implements Action { public readonly type = CUSTOM_TIME_RANGE_BADGE; public readonly id = CUSTOM_TIME_RANGE_BADGE; public order = 7; diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx index 1f148de7b5178..0c804cf584fee 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx @@ -10,7 +10,7 @@ import { intersection } from 'lodash'; import { DrilldownWizardConfig, FlyoutDrilldownWizard } from '../flyout_drilldown_wizard'; import { FlyoutListManageDrilldowns } from '../flyout_list_manage_drilldowns'; import { IStorageWrapper } from '../../../../../../../src/plugins/kibana_utils/public'; -import { Trigger, TriggerId } from '../../../../../../../src/plugins/ui_actions/public'; +import { Trigger } from '../../../../../../../src/plugins/ui_actions/public'; import { DrilldownListItem } from '../list_manage_drilldowns'; import { insufficientLicenseLevel, invalidDrilldownType } from './i18n'; import { @@ -35,7 +35,7 @@ interface ConnectedFlyoutManageDrilldownsProps< /** * List of possible triggers in current context */ - triggers: TriggerId[]; + triggers: string[]; /** * Extra action factory context passed into action factories CollectConfig, getIconType, getDisplayName and etc... @@ -61,7 +61,7 @@ export function createFlyoutManageDrilldowns({ getTrigger, }: { actionFactories: ActionFactory[]; - getTrigger: (triggerId: TriggerId) => Trigger; + getTrigger: (triggerId: string) => Trigger; storage: IStorageWrapper; toastService: ToastsStart; docsLink?: string; @@ -122,7 +122,7 @@ export function createFlyoutManageDrilldowns({ actionFactory: allActionFactoriesById[drilldownToEdit.action.factoryId], actionConfig: drilldownToEdit.action.config as BaseActionConfig, name: drilldownToEdit.action.name, - selectedTriggers: (drilldownToEdit.triggers ?? []) as TriggerId[], + selectedTriggers: (drilldownToEdit.triggers ?? []) as string[], }; } @@ -133,7 +133,7 @@ export function createFlyoutManageDrilldowns({ const actionFactory = allActionFactoriesById[drilldown.action.factoryId]; const drilldownFactoryContext: BaseActionFactoryContext = { ...props.placeContext, - triggers: drilldown.triggers as TriggerId[], + triggers: drilldown.triggers as string[], }; return { id: drilldown.eventId, @@ -146,7 +146,7 @@ export function createFlyoutManageDrilldowns({ : !actionFactory.isCompatibleLicense() ? insufficientLicenseLevel : undefined, - triggers: drilldown.triggers.map((trigger) => getTrigger(trigger as TriggerId)), + triggers: drilldown.triggers.map((trigger) => getTrigger(trigger as string)), }; } diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts index 06f63949f6d63..4851a5fab2209 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts @@ -11,7 +11,6 @@ import { UiActionsEnhancedDynamicActionManagerState as DynamicActionManagerState, UiActionsEnhancedSerializedAction, } from '../../../index'; -import { TriggerContextMapping } from '../../../../../../../src/plugins/ui_actions/public'; import { createStateContainer } from '../../../../../../../src/plugins/kibana_utils/common'; class MockDynamicActionManager implements PublicMethodsOf { @@ -29,10 +28,7 @@ class MockDynamicActionManager implements PublicMethodsOf return this.state.get().events; } - async createEvent( - action: UiActionsEnhancedSerializedAction, - triggers: Array - ) { + async createEvent(action: UiActionsEnhancedSerializedAction, triggers: string[]) { const event = { action, triggers, @@ -62,7 +58,7 @@ class MockDynamicActionManager implements PublicMethodsOf async updateEvent( eventId: string, action: UiActionsEnhancedSerializedAction, - triggers: Array + triggers: string[] ) { const state = this.state.get(); const events = state.events; diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.stories.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.stories.tsx index 2f5f7760d40bd..797792eaf9977 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.stories.tsx +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.stories.tsx @@ -9,16 +9,12 @@ import { EuiFlyout } from '@elastic/eui'; import { storiesOf } from '@storybook/react'; import { FlyoutDrilldownWizard } from './index'; import { mockActionFactories } from '../../../components/action_wizard/test_data'; -import { Trigger, TriggerId } from '../../../../../../../src/plugins/ui_actions/public'; +import { Trigger } from '../../../../../../../src/plugins/ui_actions/public'; const otherProps = { - supportedTriggers: [ - 'VALUE_CLICK_TRIGGER', - 'SELECT_RANGE_TRIGGER', - 'FILTER_TRIGGER', - ] as TriggerId[], + supportedTriggers: ['VALUE_CLICK_TRIGGER', 'SELECT_RANGE_TRIGGER', 'FILTER_TRIGGER'] as string[], onClose: () => {}, - getTrigger: (id: TriggerId) => ({ id } as Trigger), + getTrigger: (id: string) => ({ id } as Trigger), }; storiesOf('components/FlyoutDrilldownWizard', module) diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.tsx index d54bfe0af3b8b..79e94504d8e38 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.tsx +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.tsx @@ -21,14 +21,14 @@ import { BaseActionConfig, BaseActionFactoryContext, } from '../../../dynamic_actions'; -import { Trigger, TriggerId } from '../../../../../../../src/plugins/ui_actions/public'; +import { Trigger } from '../../../../../../../src/plugins/ui_actions/public'; import { ActionFactoryPlaceContext } from '../types'; export interface DrilldownWizardConfig { name: string; actionFactory?: ActionFactory; actionConfig?: ActionConfig; - selectedTriggers?: TriggerId[]; + selectedTriggers?: string[]; } export interface FlyoutDrilldownWizardProps< @@ -60,12 +60,12 @@ export interface FlyoutDrilldownWizardProps< */ triggerPickerDocsLink?: string; - getTrigger: (triggerId: TriggerId) => Trigger; + getTrigger: (triggerId: string) => Trigger; /** * List of possible triggers in current context */ - supportedTriggers: TriggerId[]; + supportedTriggers: string[]; } function useWizardConfigState( @@ -77,7 +77,7 @@ function useWizardConfigState( setName: (name: string) => void; setActionConfig: (actionConfig: BaseActionConfig) => void; setActionFactory: (actionFactory?: ActionFactory) => void; - setSelectedTriggers: (triggers?: TriggerId[]) => void; + setSelectedTriggers: (triggers?: string[]) => void; } ] { const [wizardConfig, setWizardConfig] = useState( @@ -135,7 +135,7 @@ function useWizardConfigState( }); } }, - setSelectedTriggers: (selectedTriggers: TriggerId[] = []) => { + setSelectedTriggers: (selectedTriggers: string[] = []) => { setWizardConfig({ ...wizardConfig, selectedTriggers, diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.stories.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.stories.tsx index 386ec0fb0e62b..65b3bf02eca76 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.stories.tsx +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.stories.tsx @@ -7,13 +7,13 @@ import * as React from 'react'; import { storiesOf } from '@storybook/react'; import { FormDrilldownWizard } from './index'; -import { Trigger, TriggerId } from '../../../../../../../src/plugins/ui_actions/public'; +import { Trigger } from '../../../../../../../src/plugins/ui_actions/public'; const otherProps = { - triggers: ['VALUE_CLICK_TRIGGER', 'SELECT_RANGE_TRIGGER', 'FILTER_TRIGGER'] as TriggerId[], - getTriggerInfo: (id: TriggerId) => ({ id } as Trigger), + triggers: ['VALUE_CLICK_TRIGGER', 'SELECT_RANGE_TRIGGER', 'FILTER_TRIGGER'], + getTriggerInfo: (id: string) => ({ id } as Trigger), onSelectedTriggersChange: () => {}, - actionFactoryContext: { triggers: [] as TriggerId[] }, + actionFactoryContext: { triggers: [] as string[] }, }; const DemoEditName: React.FC = () => { diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.test.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.test.tsx index 35a897913b537..0483e175b6187 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.test.tsx +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.test.tsx @@ -9,12 +9,12 @@ import { render } from 'react-dom'; import { FormDrilldownWizard } from './form_drilldown_wizard'; import { render as renderTestingLibrary, fireEvent } from '@testing-library/react'; import { txtNameOfDrilldown } from './i18n'; -import { Trigger, TriggerId } from '../../../../../../../src/plugins/ui_actions/public'; +import { Trigger } from '../../../../../../../src/plugins/ui_actions/public'; const otherProps = { - actionFactoryContext: { triggers: [] as TriggerId[] }, - triggers: ['VALUE_CLICK_TRIGGER', 'SELECT_RANGE_TRIGGER', 'FILTER_TRIGGER'] as TriggerId[], - getTriggerInfo: (id: TriggerId) => ({ id } as Trigger), + actionFactoryContext: { triggers: [] as string[] }, + triggers: ['VALUE_CLICK_TRIGGER', 'SELECT_RANGE_TRIGGER', 'FILTER_TRIGGER'] as string[], + getTriggerInfo: (id: string) => ({ id } as Trigger), onSelectedTriggersChange: () => {}, }; diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.tsx index 5f5b577706cf9..9679a8d5d3e44 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.tsx +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.tsx @@ -15,7 +15,7 @@ import { BaseActionFactoryContext, } from '../../../dynamic_actions'; import { ActionWizard } from '../../../components/action_wizard'; -import { Trigger, TriggerId } from '../../../../../../../src/plugins/ui_actions/public'; +import { Trigger } from '../../../../../../../src/plugins/ui_actions/public'; import { txtGetMoreActions } from './i18n'; const GET_MORE_ACTIONS_LINK = 'https://www.elastic.co/subscriptions'; @@ -41,14 +41,14 @@ export interface FormDrilldownWizardProps< * Trigger selection has changed * @param triggers */ - onSelectedTriggersChange: (triggers?: TriggerId[]) => void; + onSelectedTriggersChange: (triggers?: string[]) => void; - getTriggerInfo: (triggerId: TriggerId) => Trigger; + getTriggerInfo: (triggerId: string) => Trigger; /** * List of possible triggers in current context */ - triggers: TriggerId[]; + triggers: string[]; triggerPickerDocsLink?: string; } diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/drilldown_definition.ts b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/drilldown_definition.ts index b55b4b87ebccd..26e670abd7cc9 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/drilldown_definition.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/drilldown_definition.ts @@ -11,7 +11,6 @@ import { SerializedEvent, } from '../dynamic_actions'; import { LicenseType } from '../../../licensing/public'; -import { TriggerContextMapping, TriggerId } from '../../../../../src/plugins/ui_actions/public'; import { ActionExecutionContext } from '../../../../../src/plugins/ui_actions/public'; import { PersistableStateDefinition } from '../../../../../src/plugins/kibana_utils/common'; @@ -31,11 +30,8 @@ import { PersistableStateDefinition } from '../../../../../src/plugins/kibana_ut export interface DrilldownDefinition< Config extends BaseActionConfig = BaseActionConfig, - SupportedTriggers extends TriggerId = TriggerId, - FactoryContext extends BaseActionFactoryContext = { - triggers: SupportedTriggers[]; - }, - ExecutionContext extends TriggerContextMapping[SupportedTriggers] = TriggerContextMapping[SupportedTriggers] + ExecutionContext extends object = object, + FactoryContext extends BaseActionFactoryContext = BaseActionFactoryContext > extends PersistableStateDefinition { /** * Globally unique identifier for this drilldown. @@ -70,12 +66,7 @@ export interface DrilldownDefinition< /** * Function that returns default config for this drilldown. */ - createConfig: ActionFactoryDefinition< - Config, - SupportedTriggers, - FactoryContext, - ExecutionContext - >['createConfig']; + createConfig: ActionFactoryDefinition['createConfig']; /** * `UiComponent` that collections config for this drilldown. You can create @@ -96,23 +87,13 @@ export interface DrilldownDefinition< * export const CollectConfig = uiToReactComponent(ReactCollectConfig); * ``` */ - CollectConfig: ActionFactoryDefinition< - Config, - SupportedTriggers, - FactoryContext, - ExecutionContext - >['CollectConfig']; + CollectConfig: ActionFactoryDefinition['CollectConfig']; /** * A validator function for the config object. Should always return a boolean * given any input. */ - isConfigValid: ActionFactoryDefinition< - Config, - SupportedTriggers, - FactoryContext, - ExecutionContext - >['isConfigValid']; + isConfigValid: ActionFactoryDefinition['isConfigValid']; /** * Name of EUI icon to display when showing this drilldown to user. @@ -160,5 +141,5 @@ export interface DrilldownDefinition< * List of triggers supported by this drilldown type * This is used in trigger picker when configuring drilldown */ - supportedTriggers(): SupportedTriggers[]; + supportedTriggers(): string[]; } diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/hooks/use_drilldown_state_manager.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/hooks/use_drilldown_state_manager.tsx index b578e36ba0606..0a546be7e2344 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/hooks/use_drilldown_state_manager.tsx +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/hooks/use_drilldown_state_manager.tsx @@ -7,7 +7,6 @@ import { useState } from 'react'; import { ToastsStart } from 'kibana/public'; import useMountedState from 'react-use/lib/useMountedState'; -import { TriggerId } from '../../../../../../src/plugins/ui_actions/public'; import { useContainerState } from '../../../../../../src/plugins/kibana_utils/public'; import { toastDrilldownCreated, @@ -40,7 +39,7 @@ export function useDrilldownsStateManager( } } - async function createDrilldown(action: SerializedAction, selectedTriggers: TriggerId[]) { + async function createDrilldown(action: SerializedAction, selectedTriggers: string[]) { await run(async () => { await actionManager.createEvent(action, selectedTriggers); toastService.addSuccess({ @@ -53,7 +52,7 @@ export function useDrilldownsStateManager( async function editDrilldown( drilldownId: string, action: SerializedAction, - selectedTriggers: TriggerId[] + selectedTriggers: string[] ) { await run(async () => { await actionManager.updateEvent(drilldownId, action, selectedTriggers); diff --git a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts index a9c498c0210db..af7a2122fc32b 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts @@ -5,11 +5,7 @@ */ import { uiToReactComponent } from '../../../../../src/plugins/kibana_react/public'; -import { - TriggerContextMapping, - TriggerId, - UiActionsPresentable as Presentable, -} from '../../../../../src/plugins/ui_actions/public'; +import { UiActionsPresentable as Presentable } from '../../../../../src/plugins/ui_actions/public'; import { ActionFactoryDefinition } from './action_factory_definition'; import { Configurable } from '../../../../../src/plugins/kibana_utils/public'; import { @@ -30,22 +26,14 @@ export interface ActionFactoryDeps { export class ActionFactory< Config extends BaseActionConfig = BaseActionConfig, - SupportedTriggers extends TriggerId = TriggerId, - FactoryContext extends BaseActionFactoryContext = { - triggers: SupportedTriggers[]; - }, - ActionContext extends TriggerContextMapping[SupportedTriggers] = TriggerContextMapping[SupportedTriggers] + ExecutionContext extends object = object, + FactoryContext extends BaseActionFactoryContext = BaseActionFactoryContext > implements Omit, 'getHref'>, Configurable, PersistableState { constructor( - protected readonly def: ActionFactoryDefinition< - Config, - SupportedTriggers, - FactoryContext, - ActionContext - >, + protected readonly def: ActionFactoryDefinition, protected readonly deps: ActionFactoryDeps ) { if (def.minimalLicense && !def.licenseFeatureName) { @@ -100,23 +88,23 @@ export class ActionFactory< public create( serializedAction: Omit, 'factoryId'> - ): ActionDefinition { + ): ActionDefinition { const action = this.def.create(serializedAction); return { ...action, - isCompatible: async (context: ActionContext): Promise => { + isCompatible: async (context: ExecutionContext): Promise => { if (!this.isCompatibleLicense()) return false; if (!action.isCompatible) return true; return action.isCompatible(context); }, - execute: async (context: ActionContext): Promise => { + execute: async (context: ExecutionContext): Promise => { this.notifyFeatureUsage(); return action.execute(context); }, }; } - public supportedTriggers(): SupportedTriggers[] { + public supportedTriggers(): string[] { return this.def.supportedTriggers(); } diff --git a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory_definition.ts b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory_definition.ts index b4df1f827a2a3..1bfbb2edb98b5 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory_definition.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory_definition.ts @@ -13,8 +13,6 @@ import { } from './types'; import { LicenseType } from '../../../licensing/public'; import { - TriggerContextMapping, - TriggerId, UiActionsActionDefinition as ActionDefinition, UiActionsPresentable as Presentable, } from '../../../../../src/plugins/ui_actions/public'; @@ -25,11 +23,8 @@ import { PersistableStateDefinition } from '../../../../../src/plugins/kibana_ut */ export interface ActionFactoryDefinition< Config extends BaseActionConfig = BaseActionConfig, - SupportedTriggers extends TriggerId = TriggerId, - FactoryContext extends BaseActionFactoryContext = { - triggers: SupportedTriggers[]; - }, - ActionContext extends TriggerContextMapping[SupportedTriggers] = TriggerContextMapping[SupportedTriggers] + ExecutionContext extends object = object, + FactoryContext extends BaseActionFactoryContext = BaseActionFactoryContext > extends Partial, 'getHref'>>, Configurable, PersistableStateDefinition { @@ -65,7 +60,7 @@ export interface ActionFactoryDefinition< */ create( serializedAction: Omit, 'factoryId'> - ): ActionDefinition; + ): ActionDefinition; - supportedTriggers(): SupportedTriggers[]; + supportedTriggers(): string[]; } diff --git a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.ts b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.ts index f096b17f8a78d..ff8528e6791f9 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.ts @@ -7,10 +7,7 @@ import { v4 as uuidv4 } from 'uuid'; import { Subscription } from 'rxjs'; import { ActionStorage } from './dynamic_action_storage'; -import { - TriggerContextMapping, - UiActionsActionDefinition as ActionDefinition, -} from '../../../../../src/plugins/ui_actions/public'; +import { UiActionsActionDefinition as ActionDefinition } from '../../../../../src/plugins/ui_actions/public'; import { defaultState, transitions, selectors, State } from './dynamic_action_manager_state'; import { StateContainer, @@ -214,7 +211,7 @@ export class DynamicActionManager { * @param action Dynamic action for which to create an event. * @param triggers List of triggers to which action should react. */ - public async createEvent(action: SerializedAction, triggers: Array) { + public async createEvent(action: SerializedAction, triggers: string[]) { const event: SerializedEvent = { eventId: uuidv4(), triggers, @@ -245,11 +242,7 @@ export class DynamicActionManager { * @param action New action for which to create the event. * @param triggers List of triggers to which action should react. */ - public async updateEvent( - eventId: string, - action: SerializedAction, - triggers: Array - ) { + public async updateEvent(eventId: string, action: SerializedAction, triggers: string[]) { const event: SerializedEvent = { eventId, triggers, diff --git a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/types.ts b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/types.ts index 28d104093f64f..78e8b20870ed8 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/types.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/types.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { TriggerId } from '../../../../../src/plugins/ui_actions/public'; import { SerializedAction, SerializedEvent, BaseActionConfig } from '../../common/types'; export { SerializedAction, SerializedEvent, BaseActionConfig }; @@ -12,6 +11,6 @@ export { SerializedAction, SerializedEvent, BaseActionConfig }; /** * Action factory context passed into ActionFactories' CollectConfig, getDisplayName, getIconType */ -export interface BaseActionFactoryContext { - triggers: SupportedTriggers[]; +export interface BaseActionFactoryContext { + triggers: string[]; } diff --git a/x-pack/plugins/ui_actions_enhanced/public/plugin.ts b/x-pack/plugins/ui_actions_enhanced/public/plugin.ts index 31236d2ea9779..dc46f021cd77b 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/plugin.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/plugin.ts @@ -13,27 +13,15 @@ import { } from '../../../../src/core/public'; import { createReactOverlays } from '../../../../src/plugins/kibana_react/public'; import { UI_SETTINGS } from '../../../../src/plugins/data/public'; -import { - TriggerId, - UiActionsSetup, - UiActionsStart, -} from '../../../../src/plugins/ui_actions/public'; +import { UiActionsSetup, UiActionsStart } from '../../../../src/plugins/ui_actions/public'; import { CONTEXT_MENU_TRIGGER, PANEL_BADGE_TRIGGER, EmbeddableSetup, EmbeddableStart, } from '../../../../src/plugins/embeddable/public'; -import { - CustomTimeRangeAction, - CUSTOM_TIME_RANGE, - TimeRangeActionContext, -} from './custom_time_range_action'; -import { - CustomTimeRangeBadge, - CUSTOM_TIME_RANGE_BADGE, - TimeBadgeActionContext, -} from './custom_time_range_badge'; +import { CustomTimeRangeAction } from './custom_time_range_action'; +import { CustomTimeRangeBadge } from './custom_time_range_badge'; import { CommonlyUsedRange } from './types'; import { UiActionsServiceEnhancements } from './services'; import { ILicense, LicensingPluginSetup, LicensingPluginStart } from '../../licensing/public'; @@ -71,13 +59,6 @@ export interface StartContract FlyoutManageDrilldowns: ReturnType; } -declare module '../../../../src/plugins/ui_actions/public' { - export interface ActionContextMapping { - [CUSTOM_TIME_RANGE]: TimeRangeActionContext; - [CUSTOM_TIME_RANGE_BADGE]: TimeBadgeActionContext; - } -} - export class AdvancedUiActionsPublicPlugin implements Plugin { readonly licenseInfo = new BehaviorSubject(undefined); @@ -138,7 +119,7 @@ export class AdvancedUiActionsPublicPlugin ...this.enhancements!, FlyoutManageDrilldowns: createFlyoutManageDrilldowns({ actionFactories: this.enhancements!.getActionFactories(), - getTrigger: (triggerId: TriggerId) => uiActions.getTrigger(triggerId), + getTrigger: (triggerId) => uiActions.getTrigger(triggerId), storage: new Storage(window?.localStorage), toastService: core.notifications.toasts, docsLink: core.docLinks.links.dashboard.drilldowns, diff --git a/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts b/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts index 0da2dc6da2c25..2225c77a31101 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts @@ -14,7 +14,6 @@ import { } from '../dynamic_actions'; import { DrilldownDefinition } from '../drilldowns'; import { ILicense } from '../../../licensing/common/types'; -import { TriggerContextMapping, TriggerId } from '../../../../../src/plugins/ui_actions/public'; import { LicensingPluginSetup, LicensingPluginStart } from '../../../licensing/public'; import { SavedObjectReference } from '../../../../../src/core/types'; import { PersistableStateDefinition } from '../../../../../src/plugins/kibana_utils/common'; @@ -46,24 +45,19 @@ export class UiActionsServiceEnhancements */ public readonly registerActionFactory = < Config extends BaseActionConfig = BaseActionConfig, - SupportedTriggers extends TriggerId = TriggerId, - FactoryContext extends BaseActionFactoryContext = { - triggers: SupportedTriggers[]; - }, - ActionContext extends TriggerContextMapping[SupportedTriggers] = TriggerContextMapping[SupportedTriggers] + ExecutionContext extends object = object, + FactoryContext extends BaseActionFactoryContext = BaseActionFactoryContext >( - definition: ActionFactoryDefinition + definition: ActionFactoryDefinition ) => { if (this.actionFactories.has(definition.id)) { throw new Error(`ActionFactory [actionFactory.id = ${definition.id}] already registered.`); } - const actionFactory = new ActionFactory< - Config, - SupportedTriggers, - FactoryContext, - ActionContext - >(definition, this.deps); + const actionFactory = new ActionFactory( + definition, + this.deps + ); this.actionFactories.set(actionFactory.id, actionFactory as ActionFactory); this.registerFeatureUsage(definition); @@ -95,11 +89,8 @@ export class UiActionsServiceEnhancements */ public readonly registerDrilldown = < Config extends BaseActionConfig = BaseActionConfig, - SupportedTriggers extends TriggerId = TriggerId, - FactoryContext extends BaseActionFactoryContext = { - triggers: SupportedTriggers[]; - }, - ExecutionContext extends TriggerContextMapping[SupportedTriggers] = TriggerContextMapping[SupportedTriggers] + ExecutionContext extends object = object, + FactoryContext extends BaseActionFactoryContext = BaseActionFactoryContext >({ id: factoryId, isBeta, @@ -118,13 +109,8 @@ export class UiActionsServiceEnhancements telemetry, extract, inject, - }: DrilldownDefinition): void => { - const actionFactory: ActionFactoryDefinition< - Config, - SupportedTriggers, - FactoryContext, - ExecutionContext - > = { + }: DrilldownDefinition): void => { + const actionFactory: ActionFactoryDefinition = { id: factoryId, isBeta, minimalLicense, @@ -151,7 +137,7 @@ export class UiActionsServiceEnhancements ? async (context) => isCompatible(serializedAction.config, context) : undefined, }), - } as ActionFactoryDefinition; + } as ActionFactoryDefinition; this.registerActionFactory(actionFactory); }; From f22e06e618c0de7913fd31665f48fd4860dde023 Mon Sep 17 00:00:00 2001 From: Alex Close Date: Tue, 5 Jan 2021 09:26:28 +0000 Subject: [PATCH 13/32] Add timestamp range example to kql docs (#87138) A few folks have asked me if it is possible to do timestamp ranges by using "now" in kql. This was missing from an example so I have added it to the docs. (cherry picked from commit 48df620b1d30a9dcd08423204b66b453e50e587b) --- docs/discover/kuery.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/discover/kuery.asciidoc b/docs/discover/kuery.asciidoc index c1d287fca1f44..feb16190cb34b 100644 --- a/docs/discover/kuery.asciidoc +++ b/docs/discover/kuery.asciidoc @@ -111,11 +111,11 @@ tags:(success and info and security) [discrete] === Range queries -KQL supports `>`, `>=`, `<`, and `<=`. For example: +KQL supports `>`, `>=`, `<`, and `<=` on numeric and date types. For example: [source,yaml] ------------------- -account_number >= 100 and items_sold <= 200 +account_number >= 100 and items_sold <= 200 and @timestamp >= now-5m ------------------- [discrete] From 4f9b0af6ec7c7f477a812d17cb84d886c82a2446 Mon Sep 17 00:00:00 2001 From: Daniil Date: Tue, 5 Jan 2021 12:38:52 +0300 Subject: [PATCH 14/32] Remove extra external link in markdown editor (#86933) * Remove extra external icon * Add unit tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../markdown_options.test.tsx.snap | 68 +++++++++++++++++++ .../public/markdown_options.test.tsx | 56 +++++++++++++++ .../public/markdown_options.tsx | 8 +-- 3 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 src/plugins/vis_type_markdown/public/__snapshots__/markdown_options.test.tsx.snap create mode 100644 src/plugins/vis_type_markdown/public/markdown_options.test.tsx diff --git a/src/plugins/vis_type_markdown/public/__snapshots__/markdown_options.test.tsx.snap b/src/plugins/vis_type_markdown/public/__snapshots__/markdown_options.test.tsx.snap new file mode 100644 index 0000000000000..03431fe2437b7 --- /dev/null +++ b/src/plugins/vis_type_markdown/public/__snapshots__/markdown_options.test.tsx.snap @@ -0,0 +1,68 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MarkdownOptions should match snapshot 1`] = ` + + + + + + +

+ +

+
+
+ + + + + + + +
+
+ + + +
+
+`; diff --git a/src/plugins/vis_type_markdown/public/markdown_options.test.tsx b/src/plugins/vis_type_markdown/public/markdown_options.test.tsx new file mode 100644 index 0000000000000..170dde7ee91e6 --- /dev/null +++ b/src/plugins/vis_type_markdown/public/markdown_options.test.tsx @@ -0,0 +1,56 @@ +/* + * 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 React from 'react'; +import { shallow } from 'enzyme'; + +import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { MarkdownVisParams } from './types'; +import { MarkdownOptions } from './markdown_options'; + +describe('MarkdownOptions', () => { + const props = ({ + stateParams: { + fontSize: 12, + markdown: 'hello from 2020 🥳', + openLinksInNewTab: false, + }, + setValue: jest.fn(), + } as unknown) as VisOptionsProps; + + it('should match snapshot', () => { + const comp = shallow(); + expect(comp).toMatchSnapshot(); + }); + + it('should update markdown on change', () => { + const comp = shallow(); + const value = 'see you in 2021 😎'; + const textArea = comp.find('EuiTextArea'); + const onChange = textArea.prop('onChange'); + onChange?.({ + target: { + // @ts-expect-error + value, + }, + }); + + expect(props.setValue).toHaveBeenCalledWith('markdown', value); + }); +}); diff --git a/src/plugins/vis_type_markdown/public/markdown_options.tsx b/src/plugins/vis_type_markdown/public/markdown_options.tsx index a6349793619a0..674fbeb517510 100644 --- a/src/plugins/vis_type_markdown/public/markdown_options.tsx +++ b/src/plugins/vis_type_markdown/public/markdown_options.tsx @@ -22,7 +22,6 @@ import { EuiPanel, EuiTitle, EuiLink, - EuiIcon, EuiTextArea, EuiFlexGroup, EuiFlexItem, @@ -35,7 +34,7 @@ import { MarkdownVisParams } from './types'; function MarkdownOptions({ stateParams, setValue }: VisOptionsProps) { const onMarkdownUpdate = useCallback( - (value: MarkdownVisParams['markdown']) => setValue('markdown', value), + ({ target: { value } }: React.ChangeEvent) => setValue('markdown', value), [setValue] ); @@ -61,8 +60,7 @@ function MarkdownOptions({ stateParams, setValue }: VisOptionsProps{' '} - + /> @@ -74,7 +72,7 @@ function MarkdownOptions({ stateParams, setValue }: VisOptionsProps onMarkdownUpdate(value)} + onChange={onMarkdownUpdate} fullWidth={true} data-test-subj="markdownTextarea" resize="none" From fb8a1ef505aaccc8f0ffe1445afcd7ceb3aa9d9c Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 5 Jan 2021 10:51:40 +0100 Subject: [PATCH 15/32] [Uptime] Remove link to journey details page (#87146) * Disable link to details page * removed underline --- .../__snapshots__/ping_timestamp.test.tsx.snap | 13 +++++-------- .../monitor/ping_list/columns/ping_timestamp.tsx | 7 +++---- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/__tests__/__snapshots__/ping_timestamp.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/__tests__/__snapshots__/ping_timestamp.test.tsx.snap index 64e245d1eddc9..ba6076151c1d7 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/__tests__/__snapshots__/ping_timestamp.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/__tests__/__snapshots__/ping_timestamp.test.tsx.snap @@ -58,13 +58,11 @@ exports[`Ping Timestamp component render without errors 1`] = ` class="stepArrowsFullScreen" style="position:absolute;bottom:32px;width:100%" /> - Nov 26, 2020 10:28:56 AM - +
@@ -130,12 +128,11 @@ exports[`Ping Timestamp component shallow render without errors 1`] = ` } } /> - Nov 26, 2020 10:28:56 AM - + diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.tsx index 366110c0e9195..fc3b8f4d95d21 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.tsx @@ -10,7 +10,6 @@ import { EuiFlexGroup, EuiFlexItem, EuiImage, - EuiLink, EuiSpacer, EuiText, } from '@elastic/eui'; @@ -32,6 +31,7 @@ const StepImage = styled(EuiImage)` align-self: center; margin-left: 8px; margin-top: 8px; + text-decoration: none !important; } } `; @@ -132,9 +132,8 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { )}
- - {getShortTimeStamp(moment(timestamp))} - + {/* TODO: Add link to details page once it's available */} + {getShortTimeStamp(moment(timestamp))} ); From fdea747fb3f74f6e2a8936c92211dd9757ddc690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Casper=20H=C3=BCbertz?= Date: Tue, 5 Jan 2021 13:19:13 +0100 Subject: [PATCH 16/32] [APM] Settings: Move "HomeLink" into the sidebar (#87167) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixed responsive state when opening the menu * Update x-pack/plugins/apm/public/components/app/Settings/index.tsx Co-authored-by: Cauê Marcondes <55978943+cauemarcondes@users.noreply.github.com> --- .../public/components/app/Settings/index.tsx | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/Settings/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/index.tsx index e974f05fbe994..230b103c0062a 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/index.tsx @@ -10,9 +10,10 @@ import { EuiPageBody, EuiPageSideBar, EuiSideNav, + EuiSpacer, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import React, { ReactNode } from 'react'; +import React, { ReactNode, useState } from 'react'; import { RouteComponentProps } from 'react-router-dom'; import { HeaderMenuPortal } from '../../../../../observability/public'; import { ActionMenu } from '../../../application/action_menu'; @@ -30,6 +31,12 @@ export function Settings({ children, location }: SettingsProps) { const canAccessML = !!core.application.capabilities.ml?.canAccessML; const { search, pathname } = location; + const [isSideNavOpenOnMobile, setisSideNavOpenOnMobile] = useState(false); + + const toggleOpenOnMobile = () => { + setisSideNavOpenOnMobile((prevState) => !prevState); + }; + function getSettingsHref(path: string) { return getAPMHref({ basePath, path: `/settings${path}`, search }); } @@ -41,16 +48,24 @@ export function Settings({ children, location }: SettingsProps) { > - - - {i18n.translate('xpack.apm.settings.returnLinkLabel', { - defaultMessage: 'Return to inventory', - })} - - + + + {i18n.translate('xpack.apm.settings.returnLinkLabel', { + defaultMessage: 'Return to inventory', + })} + + + toggleOpenOnMobile()} + isOpenOnMobile={isSideNavOpenOnMobile} items={[ { name: i18n.translate('xpack.apm.settings.pageTitle', { From d6cf633e4f0fcc16eb38f9597f08ac95b587a8de Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Tue, 5 Jan 2021 07:37:14 -0500 Subject: [PATCH 17/32] Introduce mechanism to request default capabilities (#86473) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- ...rver.capabilitiessetup.registerswitcher.md | 14 +++++- ...plugin-core-server.capabilitiesswitcher.md | 2 +- .../capabilities/capabilities_service.test.ts | 27 ++++++++++- .../capabilities/capabilities_service.tsx | 2 + .../capabilities/capabilities_service.ts | 16 ++++++- .../capabilities_service.test.ts | 46 +++++++++++++++++-- .../capabilities/resolve_capabilities.test.ts | 12 ++--- .../capabilities/resolve_capabilities.ts | 19 ++++++-- .../routes/resolve_capabilities.ts | 6 ++- src/core/server/capabilities/types.ts | 3 +- src/core/server/server.api.md | 2 +- .../spaces_manager/spaces_manager.test.ts | 28 +++-------- .../public/spaces_manager/spaces_manager.ts | 21 +++++---- .../capabilities_switcher.test.ts | 35 ++++++++++---- .../capabilities/capabilities_switcher.ts | 7 +-- 15 files changed, 178 insertions(+), 62 deletions(-) diff --git a/docs/development/core/server/kibana-plugin-core-server.capabilitiessetup.registerswitcher.md b/docs/development/core/server/kibana-plugin-core-server.capabilitiessetup.registerswitcher.md index d0fd524f3234f..715f15ec812a3 100644 --- a/docs/development/core/server/kibana-plugin-core-server.capabilitiessetup.registerswitcher.md +++ b/docs/development/core/server/kibana-plugin-core-server.capabilitiessetup.registerswitcher.md @@ -31,7 +31,19 @@ How to restrict some capabilities ```ts // my-plugin/server/plugin.ts public setup(core: CoreSetup, deps: {}) { - core.capabilities.registerSwitcher((request, capabilities) => { + core.capabilities.registerSwitcher((request, capabilities, useDefaultCapabilities) => { + // useDefaultCapabilities is a special case that switchers typically don't have to concern themselves with. + // The default capabilities are typically the ones you provide in your CapabilitiesProvider, but this flag + // gives each switcher an opportunity to change the default capabilities of other plugins' capabilities. + // For example, you may decide to flip another plugin's capability to false if today is Tuesday, + // but you wouldn't want to do this when we are requesting the default set of capabilities. + if (useDefaultCapabilities) { + return { + somePlugin: { + featureEnabledByDefault: true + } + } + } if(myPluginApi.shouldRestrictSomePluginBecauseOf(request)) { return { somePlugin: { diff --git a/docs/development/core/server/kibana-plugin-core-server.capabilitiesswitcher.md b/docs/development/core/server/kibana-plugin-core-server.capabilitiesswitcher.md index 01aa3a32c9abb..e6a0a9a096671 100644 --- a/docs/development/core/server/kibana-plugin-core-server.capabilitiesswitcher.md +++ b/docs/development/core/server/kibana-plugin-core-server.capabilitiesswitcher.md @@ -9,5 +9,5 @@ See [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) Signature: ```typescript -export declare type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities) => Partial | Promise>; +export declare type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities, useDefaultCapabilities: boolean) => Partial | Promise>; ``` diff --git a/src/core/public/application/capabilities/capabilities_service.test.ts b/src/core/public/application/capabilities/capabilities_service.test.ts index 286a93fdc2398..aa9c10ecfb2b2 100644 --- a/src/core/public/application/capabilities/capabilities_service.test.ts +++ b/src/core/public/application/capabilities/capabilities_service.test.ts @@ -41,11 +41,36 @@ describe('#start', () => { http.post.mockReturnValue(Promise.resolve(mockedCapabilities)); }); + it('requests default capabilities on anonymous paths', async () => { + http.anonymousPaths.isAnonymous.mockReturnValue(true); + const service = new CapabilitiesService(); + const appIds = ['app1', 'app2', 'legacyApp1', 'legacyApp2']; + const { capabilities } = await service.start({ + http, + appIds, + }); + + expect(http.post).toHaveBeenCalledWith('/api/core/capabilities', { + query: { + useDefaultCapabilities: true, + }, + body: JSON.stringify({ applications: appIds }), + }); + + // @ts-expect-error TypeScript knows this shouldn't be possible + expect(() => (capabilities.foo = 'foo')).toThrowError(); + }); + it('only returns capabilities for given appIds', async () => { const service = new CapabilitiesService(); + const appIds = ['app1', 'app2', 'legacyApp1', 'legacyApp2']; const { capabilities } = await service.start({ http, - appIds: ['app1', 'app2', 'legacyApp1', 'legacyApp2'], + appIds, + }); + + expect(http.post).toHaveBeenCalledWith('/api/core/capabilities', { + body: JSON.stringify({ applications: appIds }), }); // @ts-expect-error TypeScript knows this shouldn't be possible diff --git a/src/core/public/application/capabilities/capabilities_service.tsx b/src/core/public/application/capabilities/capabilities_service.tsx index 1164164aec4c5..156b75b2d8abe 100644 --- a/src/core/public/application/capabilities/capabilities_service.tsx +++ b/src/core/public/application/capabilities/capabilities_service.tsx @@ -38,7 +38,9 @@ export interface CapabilitiesStart { */ export class CapabilitiesService { public async start({ appIds, http }: StartDeps): Promise { + const useDefaultCapabilities = http.anonymousPaths.isAnonymous(window.location.pathname); const capabilities = await http.post('/api/core/capabilities', { + query: useDefaultCapabilities ? { useDefaultCapabilities } : undefined, body: JSON.stringify({ applications: appIds }), }); diff --git a/src/core/server/capabilities/capabilities_service.ts b/src/core/server/capabilities/capabilities_service.ts index f0be9743d4d60..9af945d17b2ad 100644 --- a/src/core/server/capabilities/capabilities_service.ts +++ b/src/core/server/capabilities/capabilities_service.ts @@ -76,7 +76,19 @@ export interface CapabilitiesSetup { * ```ts * // my-plugin/server/plugin.ts * public setup(core: CoreSetup, deps: {}) { - * core.capabilities.registerSwitcher((request, capabilities) => { + * core.capabilities.registerSwitcher((request, capabilities, useDefaultCapabilities) => { + * // useDefaultCapabilities is a special case that switchers typically don't have to concern themselves with. + * // The default capabilities are typically the ones you provide in your CapabilitiesProvider, but this flag + * // gives each switcher an opportunity to change the default capabilities of other plugins' capabilities. + * // For example, you may decide to flip another plugin's capability to false if today is Tuesday, + * // but you wouldn't want to do this when we are requesting the default set of capabilities. + * if (useDefaultCapabilities) { + * return { + * somePlugin: { + * featureEnabledByDefault: true + * } + * } + * } * if(myPluginApi.shouldRestrictSomePluginBecauseOf(request)) { * return { * somePlugin: { @@ -150,7 +162,7 @@ export class CapabilitiesService { public start(): CapabilitiesStart { return { - resolveCapabilities: (request) => this.resolveCapabilities(request, []), + resolveCapabilities: (request) => this.resolveCapabilities(request, [], false), }; } } diff --git a/src/core/server/capabilities/integration_tests/capabilities_service.test.ts b/src/core/server/capabilities/integration_tests/capabilities_service.test.ts index 17f2c77bbf660..4217dd98ae735 100644 --- a/src/core/server/capabilities/integration_tests/capabilities_service.test.ts +++ b/src/core/server/capabilities/integration_tests/capabilities_service.test.ts @@ -72,17 +72,57 @@ describe('CapabilitiesService', () => { `); }); - it('uses the service capabilities providers', async () => { - serviceSetup.registerProvider(() => ({ + it('uses the service capabilities providers and switchers', async () => { + const getInitialCapabilities = () => ({ catalogue: { something: true, }, - })); + management: {}, + navLinks: {}, + }); + serviceSetup.registerProvider(() => getInitialCapabilities()); + + const switcher = jest.fn((_, capabilities) => capabilities); + serviceSetup.registerSwitcher(switcher); const result = await supertest(httpSetup.server.listener) .post('/api/core/capabilities') .send({ applications: [] }) .expect(200); + + expect(switcher).toHaveBeenCalledTimes(1); + expect(switcher).toHaveBeenCalledWith(expect.anything(), getInitialCapabilities(), false); + expect(result.body).toMatchInlineSnapshot(` + Object { + "catalogue": Object { + "something": true, + }, + "management": Object {}, + "navLinks": Object {}, + } + `); + }); + + it('passes useDefaultCapabilities to registered switchers', async () => { + const getInitialCapabilities = () => ({ + catalogue: { + something: true, + }, + management: {}, + navLinks: {}, + }); + serviceSetup.registerProvider(() => getInitialCapabilities()); + + const switcher = jest.fn((_, capabilities) => capabilities); + serviceSetup.registerSwitcher(switcher); + + const result = await supertest(httpSetup.server.listener) + .post('/api/core/capabilities?useDefaultCapabilities=true') + .send({ applications: [] }) + .expect(200); + + expect(switcher).toHaveBeenCalledTimes(1); + expect(switcher).toHaveBeenCalledWith(expect.anything(), getInitialCapabilities(), true); expect(result.body).toMatchInlineSnapshot(` Object { "catalogue": Object { diff --git a/src/core/server/capabilities/resolve_capabilities.test.ts b/src/core/server/capabilities/resolve_capabilities.test.ts index 372efeff21ae2..21c723ea1ddc3 100644 --- a/src/core/server/capabilities/resolve_capabilities.test.ts +++ b/src/core/server/capabilities/resolve_capabilities.test.ts @@ -36,7 +36,7 @@ describe('resolveCapabilities', () => { }); it('returns the initial capabilities if no switcher are used', async () => { - const result = await resolveCapabilities(defaultCaps, [], request, []); + const result = await resolveCapabilities(defaultCaps, [], request, [], true); expect(result).toEqual(defaultCaps); }); @@ -55,7 +55,7 @@ describe('resolveCapabilities', () => { A: false, }, }); - const result = await resolveCapabilities(caps, [switcher], request, []); + const result = await resolveCapabilities(caps, [switcher], request, [], true); expect(result).toMatchInlineSnapshot(` Object { "catalogue": Object { @@ -83,7 +83,7 @@ describe('resolveCapabilities', () => { A: false, }, }); - await resolveCapabilities(caps, [switcher], request, []); + await resolveCapabilities(caps, [switcher], request, [], true); expect(caps.catalogue).toEqual({ A: true, B: true, @@ -105,7 +105,7 @@ describe('resolveCapabilities', () => { C: false, }, }); - const result = await resolveCapabilities(caps, [switcher], request, []); + const result = await resolveCapabilities(caps, [switcher], request, [], true); expect(result.catalogue).toEqual({ A: true, B: true, @@ -127,7 +127,7 @@ describe('resolveCapabilities', () => { .filter(([key]) => key !== 'B') .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}), }); - const result = await resolveCapabilities(caps, [switcher], request, []); + const result = await resolveCapabilities(caps, [switcher], request, [], true); expect(result.catalogue).toEqual({ A: true, B: true, @@ -153,7 +153,7 @@ describe('resolveCapabilities', () => { record: false, }, }); - const result = await resolveCapabilities(caps, [switcher], request, []); + const result = await resolveCapabilities(caps, [switcher], request, [], true); expect(result.section).toEqual({ boolean: true, record: { diff --git a/src/core/server/capabilities/resolve_capabilities.ts b/src/core/server/capabilities/resolve_capabilities.ts index 1be504d4bc314..6f4eff6b882d0 100644 --- a/src/core/server/capabilities/resolve_capabilities.ts +++ b/src/core/server/capabilities/resolve_capabilities.ts @@ -23,7 +23,8 @@ import { KibanaRequest } from '../http'; export type CapabilitiesResolver = ( request: KibanaRequest, - applications: string[] + applications: string[], + useDefaultCapabilities: boolean ) => Promise; export const getCapabilitiesResolver = ( @@ -31,16 +32,24 @@ export const getCapabilitiesResolver = ( switchers: () => CapabilitiesSwitcher[] ): CapabilitiesResolver => async ( request: KibanaRequest, - applications: string[] + applications: string[], + useDefaultCapabilities: boolean ): Promise => { - return resolveCapabilities(capabilities(), switchers(), request, applications); + return resolveCapabilities( + capabilities(), + switchers(), + request, + applications, + useDefaultCapabilities + ); }; export const resolveCapabilities = async ( capabilities: Capabilities, switchers: CapabilitiesSwitcher[], request: KibanaRequest, - applications: string[] + applications: string[], + useDefaultCapabilities: boolean ): Promise => { const mergedCaps = cloneDeep({ ...capabilities, @@ -54,7 +63,7 @@ export const resolveCapabilities = async ( }); return switchers.reduce(async (caps, switcher) => { const resolvedCaps = await caps; - const changes = await switcher(request, resolvedCaps); + const changes = await switcher(request, resolvedCaps, useDefaultCapabilities); return recursiveApplyChanges(resolvedCaps, changes); }, Promise.resolve(mergedCaps)); }; diff --git a/src/core/server/capabilities/routes/resolve_capabilities.ts b/src/core/server/capabilities/routes/resolve_capabilities.ts index 3fb1bb3d13d0b..3694c4b894684 100644 --- a/src/core/server/capabilities/routes/resolve_capabilities.ts +++ b/src/core/server/capabilities/routes/resolve_capabilities.ts @@ -29,14 +29,18 @@ export function registerCapabilitiesRoutes(router: IRouter, resolver: Capabiliti authRequired: 'optional', }, validate: { + query: schema.object({ + useDefaultCapabilities: schema.boolean({ defaultValue: false }), + }), body: schema.object({ applications: schema.arrayOf(schema.string()), }), }, }, async (ctx, req, res) => { + const { useDefaultCapabilities } = req.query; const { applications } = req.body; - const capabilities = await resolver(req, applications); + const capabilities = await resolver(req, applications, useDefaultCapabilities); return res.ok({ body: capabilities, }); diff --git a/src/core/server/capabilities/types.ts b/src/core/server/capabilities/types.ts index 105233761a437..efef31dcc8417 100644 --- a/src/core/server/capabilities/types.ts +++ b/src/core/server/capabilities/types.ts @@ -34,5 +34,6 @@ export type CapabilitiesProvider = () => Partial; */ export type CapabilitiesSwitcher = ( request: KibanaRequest, - uiCapabilities: Capabilities + uiCapabilities: Capabilities, + useDefaultCapabilities: boolean ) => Partial | Promise>; diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index cef5f33726ed5..848cd3a657e9c 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -310,7 +310,7 @@ export interface CapabilitiesStart { } // @public -export type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities) => Partial | Promise>; +export type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities, useDefaultCapabilities: boolean) => Partial | Promise>; // @alpha export const config: { diff --git a/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.test.ts b/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.test.ts index bc861964bf56d..25e1a0e071197 100644 --- a/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.test.ts +++ b/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.test.ts @@ -10,16 +10,9 @@ import { nextTick } from '@kbn/test/jest'; describe('SpacesManager', () => { describe('#constructor', () => { - it('attempts to retrieve the active space', () => { + it('does not attempt to retrieve the active space', () => { const coreStart = coreMock.createStart(); new SpacesManager(coreStart.http); - expect(coreStart.http.get).toHaveBeenCalledWith('/internal/spaces/_active_space'); - }); - - it('does not retrieve the active space if on an anonymous path', () => { - const coreStart = coreMock.createStart(); - coreStart.http.anonymousPaths.isAnonymous.mockReturnValue(true); - new SpacesManager(coreStart.http); expect(coreStart.http.get).not.toHaveBeenCalled(); }); }); @@ -32,6 +25,7 @@ describe('SpacesManager', () => { name: 'my space', }); const spacesManager = new SpacesManager(coreStart.http); + await spacesManager.getActiveSpace(); expect(coreStart.http.get).toHaveBeenCalledWith('/internal/spaces/_active_space'); await nextTick(); @@ -50,7 +44,7 @@ describe('SpacesManager', () => { const spacesManager = new SpacesManager(coreStart.http); expect(coreStart.http.get).not.toHaveBeenCalled(); - expect(() => spacesManager.getActiveSpace()).toThrowErrorMatchingInlineSnapshot( + expect(() => spacesManager.getActiveSpace()).rejects.toThrowErrorMatchingInlineSnapshot( `"Cannot retrieve the active space for anonymous paths"` ); }); @@ -68,9 +62,6 @@ describe('SpacesManager', () => { }); const spacesManager = new SpacesManager(coreStart.http); - expect(coreStart.http.get).toHaveBeenCalledWith('/internal/spaces/_active_space'); - - await nextTick(); const activeSpace = await spacesManager.getActiveSpace(); expect(activeSpace).toEqual({ @@ -99,7 +90,7 @@ describe('SpacesManager', () => { expect(() => spacesManager.getActiveSpace({ forceRefresh: true }) - ).toThrowErrorMatchingInlineSnapshot( + ).rejects.toThrowErrorMatchingInlineSnapshot( `"Cannot retrieve the active space for anonymous paths"` ); }); @@ -111,10 +102,9 @@ describe('SpacesManager', () => { const shareToAllSpaces = Symbol(); coreStart.http.get.mockResolvedValue({ shareToAllSpaces }); const spacesManager = new SpacesManager(coreStart.http); - expect(coreStart.http.get).toHaveBeenCalledTimes(1); // initial call to get active space const result = await spacesManager.getShareSavedObjectPermissions('foo'); - expect(coreStart.http.get).toHaveBeenCalledTimes(2); + expect(coreStart.http.get).toHaveBeenCalledTimes(1); expect(coreStart.http.get).toHaveBeenLastCalledWith( '/internal/security/_share_saved_object_permissions', { @@ -126,17 +116,15 @@ describe('SpacesManager', () => { it('allows the share if security is disabled', async () => { const coreStart = coreMock.createStart(); - coreStart.http.get.mockResolvedValueOnce({}); coreStart.http.get.mockRejectedValueOnce({ body: { statusCode: 404, }, }); const spacesManager = new SpacesManager(coreStart.http); - expect(coreStart.http.get).toHaveBeenCalledTimes(1); // initial call to get active space const result = await spacesManager.getShareSavedObjectPermissions('foo'); - expect(coreStart.http.get).toHaveBeenCalledTimes(2); + expect(coreStart.http.get).toHaveBeenCalledTimes(1); expect(coreStart.http.get).toHaveBeenLastCalledWith( '/internal/security/_share_saved_object_permissions', { @@ -148,16 +136,14 @@ describe('SpacesManager', () => { it('throws all other errors', async () => { const coreStart = coreMock.createStart(); - coreStart.http.get.mockResolvedValueOnce({}); coreStart.http.get.mockRejectedValueOnce(new Error('Get out of here!')); const spacesManager = new SpacesManager(coreStart.http); - expect(coreStart.http.get).toHaveBeenCalledTimes(1); // initial call to get active space await expect( spacesManager.getShareSavedObjectPermissions('foo') ).rejects.toThrowErrorMatchingInlineSnapshot(`"Get out of here!"`); - expect(coreStart.http.get).toHaveBeenCalledTimes(2); + expect(coreStart.http.get).toHaveBeenCalledTimes(1); expect(coreStart.http.get).toHaveBeenLastCalledWith( '/internal/security/_share_saved_object_permissions', { diff --git a/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts b/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts index 856899c127fd2..a7d74de603505 100644 --- a/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts +++ b/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts @@ -22,16 +22,21 @@ export class SpacesManager { private readonly serverBasePath: string; - public readonly onActiveSpaceChange$: Observable; + private readonly _onActiveSpaceChange$: Observable; constructor(private readonly http: HttpSetup) { this.serverBasePath = http.basePath.serverBasePath; - this.onActiveSpaceChange$ = this.activeSpace$ + this._onActiveSpaceChange$ = this.activeSpace$ .asObservable() .pipe(skipWhile((v: Space | null) => v == null)) as Observable; + } - this.refreshActiveSpace(); + public get onActiveSpaceChange$() { + if (!this.activeSpace$.value) { + this.refreshActiveSpace(); + } + return this._onActiveSpaceChange$; } public async getSpaces(options: GetAllSpacesOptions = {}): Promise { @@ -44,14 +49,14 @@ export class SpacesManager { return await this.http.get(`/api/spaces/space/${encodeURIComponent(id)}`); } - public getActiveSpace({ forceRefresh = false } = {}) { + public async getActiveSpace({ forceRefresh = false } = {}) { if (this.isAnonymousPath()) { throw new Error(`Cannot retrieve the active space for anonymous paths`); } - if (!forceRefresh && this.activeSpace$.value) { - return Promise.resolve(this.activeSpace$.value); + if (forceRefresh || !this.activeSpace$.value) { + await this.refreshActiveSpace(); } - return this.http.get('/internal/spaces/_active_space') as Promise; + return this.activeSpace$.value!; } public async createSpace(space: Space) { @@ -149,7 +154,7 @@ export class SpacesManager { if (this.isAnonymousPath()) { return; } - const activeSpace = await this.getActiveSpace({ forceRefresh: true }); + const activeSpace = await this.http.get('/internal/spaces/_active_space'); this.activeSpace$.next(activeSpace); } diff --git a/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.test.ts b/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.test.ts index bfd73984811ef..770f8a16560ec 100644 --- a/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.test.ts +++ b/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.test.ts @@ -152,7 +152,7 @@ describe('capabilitiesSwitcher', () => { const { switcher } = setup(space); const request = httpServerMock.createKibanaRequest(); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); expect(result).toEqual(buildCapabilities()); }); @@ -166,12 +166,31 @@ describe('capabilitiesSwitcher', () => { const capabilities = buildCapabilities(); - const { switcher } = setup(space); + const { switcher, spacesService } = setup(space); const request = httpServerMock.createKibanaRequest({ routeAuthRequired: false }); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); + + expect(result).toEqual(buildCapabilities()); + expect(spacesService.getActiveSpace).not.toHaveBeenCalled(); + }); + + it('does not toggle capabilities when the default capabilities are requested', async () => { + const space: Space = { + id: 'space', + name: '', + disabledFeatures: ['feature_1', 'feature_2', 'feature_3'], + }; + + const capabilities = buildCapabilities(); + + const { switcher, spacesService } = setup(space); + const request = httpServerMock.createKibanaRequest(); + + const result = await switcher(request, capabilities, true); expect(result).toEqual(buildCapabilities()); + expect(spacesService.getActiveSpace).not.toHaveBeenCalled(); }); it('logs a debug message, and does not toggle capabilities if an error is encountered', async () => { @@ -188,7 +207,7 @@ describe('capabilitiesSwitcher', () => { spacesService.getActiveSpace.mockRejectedValue(new Error('Something terrible happened')); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); expect(result).toEqual(buildCapabilities()); expect(logger.debug).toHaveBeenCalledWith( @@ -207,7 +226,7 @@ describe('capabilitiesSwitcher', () => { const { switcher } = setup(space); const request = httpServerMock.createKibanaRequest(); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); expect(result).toEqual(buildCapabilities()); }); @@ -223,7 +242,7 @@ describe('capabilitiesSwitcher', () => { const { switcher } = setup(space); const request = httpServerMock.createKibanaRequest(); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); const expectedCapabilities = buildCapabilities(); @@ -247,7 +266,7 @@ describe('capabilitiesSwitcher', () => { const { switcher } = setup(space); const request = httpServerMock.createKibanaRequest(); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); const expectedCapabilities = buildCapabilities(); @@ -274,7 +293,7 @@ describe('capabilitiesSwitcher', () => { const { switcher } = setup(space); const request = httpServerMock.createKibanaRequest(); - const result = await switcher(request, capabilities); + const result = await switcher(request, capabilities, false); const expectedCapabilities = buildCapabilities(); diff --git a/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.ts b/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.ts index ee059f7b9c26e..4bf4c0683f570 100644 --- a/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.ts +++ b/x-pack/plugins/spaces/server/capabilities/capabilities_switcher.ts @@ -15,10 +15,11 @@ export function setupCapabilitiesSwitcher( getSpacesService: () => SpacesServiceStart, logger: Logger ): CapabilitiesSwitcher { - return async (request, capabilities) => { - const isAnonymousRequest = !request.route.options.authRequired; + return async (request, capabilities, useDefaultCapabilities) => { + const isAuthRequiredOrOptional = !request.route.options.authRequired; + const shouldNotToggleCapabilities = isAuthRequiredOrOptional || useDefaultCapabilities; - if (isAnonymousRequest) { + if (shouldNotToggleCapabilities) { return capabilities; } From bece59985615264d7ad534acf7b50497dd934055 Mon Sep 17 00:00:00 2001 From: Marius Dragomir Date: Tue, 5 Jan 2021 13:45:42 +0100 Subject: [PATCH 18/32] Add standlone EMS server integration test (#87070) * Initial EMS integration test * Convert to TS * extra cleanup and comments * Removed common page objects Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../apps/maps/_maps.ts | 37 +++++++++++++++++++ .../apps/maps/index.ts | 12 ++++++ 2 files changed, 49 insertions(+) create mode 100644 x-pack/test/stack_functional_integration/apps/maps/_maps.ts create mode 100644 x-pack/test/stack_functional_integration/apps/maps/index.ts diff --git a/x-pack/test/stack_functional_integration/apps/maps/_maps.ts b/x-pack/test/stack_functional_integration/apps/maps/_maps.ts new file mode 100644 index 0000000000000..cde5f950b0946 --- /dev/null +++ b/x-pack/test/stack_functional_integration/apps/maps/_maps.ts @@ -0,0 +1,37 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../functional/ftr_provider_context'; + +export default function ({ + getService, + getPageObjects, + updateBaselines, +}: FtrProviderContext & { updateBaselines: boolean }) { + const screenshot = getService('screenshots'); + const browser = getService('browser'); + const PageObjects = getPageObjects(['maps']); + + describe('check Elastic Maps Server', function () { + before(async function () { + await PageObjects.maps.loadSavedMap('EMS Test'); + await browser.setScreenshotSize(1000, 1000); + }); + + it('[ElasticMapsService] EMS Test should match screenshot', async function () { + const percentDifference = await screenshot.compareAgainstBaseline( + 'ems_test', + updateBaselines + ); + // This test should show about a 5% difference if it falls back to the online Elastic Maps Service + // and around 20% if the self-hosted doesn't load/work for some reason. This way we catch both scenarios. + // Any minor UI changes will be caught in the 1% difference that is allowed for without impacting the map. + // More info here: https://github.com/elastic/kibana/pull/87070 + expect(percentDifference).to.be.lessThan(0.01); + }); + }); +} diff --git a/x-pack/test/stack_functional_integration/apps/maps/index.ts b/x-pack/test/stack_functional_integration/apps/maps/index.ts new file mode 100644 index 0000000000000..40e5ed8f390e0 --- /dev/null +++ b/x-pack/test/stack_functional_integration/apps/maps/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { FtrProviderContext } from '../../../functional/ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('maps app', function () { + loadTestFile(require.resolve('./_maps')); + }); +} From 875fde58fe438e46ec60a7bf1af123f1c9c35eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= Date: Tue, 5 Jan 2021 08:04:58 -0500 Subject: [PATCH 19/32] Improve webhook errror messages (#87044) * Initial work * Fix variables to pull from * Rename some variables Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/builtin_action_types/webhook.ts | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/actions/server/builtin_action_types/webhook.ts b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts index 3d872d6e7e311..089363990643f 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/webhook.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts @@ -176,8 +176,14 @@ export async function executor( const { error } = result; if (error.response) { - const { status, statusText, headers: responseHeaders } = error.response; - const message = `[${status}] ${statusText}`; + const { + status, + statusText, + headers: responseHeaders, + data: { message: responseMessage }, + } = error.response; + const responseMessageAsSuffix = responseMessage ? `: ${responseMessage}` : ''; + const message = `[${status}] ${statusText}${responseMessageAsSuffix}`; logger.error(`error on ${actionId} webhook event: ${message}`); // The request was made and the server responded with a status code // that falls out of the range of 2xx @@ -195,6 +201,10 @@ export async function executor( ); } return errorResultInvalid(actionId, message); + } else if (error.isAxiosError) { + const message = `[${error.code}] ${error.message}`; + logger.error(`error on ${actionId} webhook event: ${message}`); + return errorResultRequestFailed(actionId, message); } logger.error(`error on ${actionId} webhook action: unexpected error`); @@ -222,6 +232,21 @@ function errorResultInvalid( }; } +function errorResultRequestFailed( + actionId: string, + serviceMessage: string +): ActionTypeExecutorResult { + const errMessage = i18n.translate('xpack.actions.builtin.webhook.requestFailedErrorMessage', { + defaultMessage: 'error calling webhook, request failed', + }); + return { + status: 'error', + message: errMessage, + actionId, + serviceMessage, + }; +} + function errorResultUnexpectedError(actionId: string): ActionTypeExecutorResult { const errMessage = i18n.translate('xpack.actions.builtin.webhook.unreachableErrorMessage', { defaultMessage: 'error calling webhook, unexpected error', From f0f88437b2d04a0849f1d9299b27a17f1268a05e Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Tue, 5 Jan 2021 09:06:43 -0500 Subject: [PATCH 20/32] uptime add title to waterfall sidebar truncated text (#87102) * uptime add title to waterfall sidebar truncated text * Uptime add tooltip and screen reader only text to MiddleTruncatedText Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/middle_truncated_text.test.tsx | 34 ++++++++++--------- .../components/middle_truncated_text.tsx | 22 ++++++++---- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.test.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.test.tsx index 4f54a347d22d2..9a863ab4353cf 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.test.tsx @@ -5,35 +5,37 @@ */ import { getChunks, MiddleTruncatedText } from './middle_truncated_text'; -import { shallowWithIntl } from '@kbn/test/jest'; +import { render, within } from '@testing-library/react'; import React from 'react'; const longString = 'this-is-a-really-really-really-really-really-really-really-really-long-string.madeup.extension'; +const first = 'this-is-a-really-really-really-really-really-really-really-really-long-string.made'; +const last = 'up.extension'; describe('getChunks', () => { it('Calculates chunks correctly', () => { const result = getChunks(longString); expect(result).toEqual({ - first: 'this-is-a-really-really-really-really-really-really-really-really-long-string.made', - last: 'up.extension', + first, + last, }); }); }); describe('Component', () => { - it('Renders correctly', () => { - expect(shallowWithIntl()).toMatchInlineSnapshot(` - - - - this-is-a-really-really-really-really-really-really-really-really-long-string.made - - - up.extension - - - - `); + it('renders truncated text', () => { + const { getByText } = render(); + + expect(getByText(first)).toBeInTheDocument(); + expect(getByText(last)).toBeInTheDocument(); + }); + + it('renders screen reader only text', () => { + const { getByTestId } = render(); + + const { getByText } = within(getByTestId('middleTruncatedTextSROnly')); + + expect(getByText(longString)).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx index 519927d7db28b..8479ee5cae195 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx @@ -6,6 +6,7 @@ import React, { useMemo } from 'react'; import styled from 'styled-components'; +import { EuiScreenReaderOnly, EuiToolTip } from '@elastic/eui'; const OuterContainer = styled.div` width: 100%; @@ -13,7 +14,7 @@ const OuterContainer = styled.div` position: relative; `; -const InnerContainer = styled.div` +const InnerContainer = styled.span` position: absolute; top: 0; bottom: 0; @@ -51,11 +52,18 @@ export const MiddleTruncatedText = ({ text }: { text: string }) => { }, [text]); return ( - - - {chunks.first} - {chunks.last} - - + <> + + + {text} + + + + {chunks.first} + {chunks.last} + + + + ); }; From f048ae616a7128d5e0a8c0fa1a990799120ea367 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 5 Jan 2021 06:21:10 -0800 Subject: [PATCH 21/32] Add more URLs to documentation link service (#87265) --- ...-plugin-core-public.doclinksstart.links.md | 4 ++ ...kibana-plugin-core-public.doclinksstart.md | 2 +- .../public/doc_links/doc_links_service.ts | 40 ++++++++++++++++++- src/core/public/public.api.md | 4 ++ 4 files changed, 48 insertions(+), 2 deletions(-) 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 b0730d1b762d6..fd620d31a1e64 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 @@ -74,6 +74,7 @@ readonly links: { readonly sum: string; readonly top_hits: string; }; + readonly runtimeFields: string; readonly scriptedFields: { readonly scriptFields: string; readonly scriptAggs: string; @@ -88,6 +89,7 @@ readonly links: { }; readonly addData: string; readonly kibana: string; + readonly elasticsearch: Record; readonly siem: { readonly guide: string; readonly gettingStarted: string; @@ -111,5 +113,7 @@ readonly links: { readonly maps: Record; readonly monitoring: Record; readonly security: Record; + readonly watcher: Record; + readonly ccs: Record; }; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md index 2d06876f42b6a..3ad747a42f84e 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md @@ -17,5 +17,5 @@ export interface DocLinksStart | --- | --- | --- | | [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | | | [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | | -| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly addData: string;
readonly kibana: string;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Record<string, string>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Record<string, string>;
} | | +| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: string;
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly addData: string;
readonly kibana: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Record<string, string>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Record<string, string>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
} | | diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 0c65a26b2387b..35cd58237408f 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -102,6 +102,7 @@ export class DocLinksService { sum: `${ELASTICSEARCH_DOCS}search-aggregations-metrics-sum-aggregation.html`, top_hits: `${ELASTICSEARCH_DOCS}search-aggregations-metrics-top-hits-aggregation.html`, }, + runtimeFields: `${ELASTICSEARCH_DOCS}runtime.html`, scriptedFields: { scriptFields: `${ELASTICSEARCH_DOCS}search-request-script-fields.html`, scriptAggs: `${ELASTICSEARCH_DOCS}search-aggregations.html#_values_source`, @@ -117,6 +118,13 @@ export class DocLinksService { }, addData: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/connect-to-elasticsearch.html`, kibana: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/index.html`, + elasticsearch: { + remoteClusters: `${ELASTICSEARCH_DOCS}modules-remote-clusters.html`, + remoteClustersProxy: `${ELASTICSEARCH_DOCS}modules-remote-clusters.html#proxy-mode`, + remoteClusersProxySettings: `${ELASTICSEARCH_DOCS}modules-remote-clusters.html#remote-cluster-proxy-settings`, + scriptParameters: `${ELASTICSEARCH_DOCS}modules-scripting-using.html#prefer-params`, + transportSettings: `${ELASTICSEARCH_DOCS}modules-transport.html`, + }, siem: { guide: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/index.html`, gettingStarted: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/index.html`, @@ -166,6 +174,16 @@ export class DocLinksService { alerting: { guide: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/managing-alerts-and-actions.html`, actionTypes: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/action-types.html`, + emailAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/email-action-type.html`, + generalSettings: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/alert-action-settings-kb.html#general-alert-action-settings`, + indexAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/index-action-type.html`, + indexThreshold: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/alert-types.html#alert-type-index-threshold`, + pagerDutyAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/pagerduty-action-type.html`, + preconfiguredConnectors: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/pre-configured-action-types-and-connectors.html`, + serviceNowAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/servicenow-action-type.html`, + setupPrerequisites: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/alerting-getting-started.html#alerting-setup-prerequisites`, + slackAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/slack-action-type.html`, + teamsAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/teams-action-type.html`, }, maps: { guide: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/kibana-maps.html`, @@ -176,12 +194,23 @@ export class DocLinksService { monitorKibana: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/monitoring-metricbeat.html`, }, security: { + apiKeyServiceSettings: `${ELASTICSEARCH_DOCS}security-settings.html#api-key-service-settings`, + clusterPrivileges: `${ELASTICSEARCH_DOCS}security-privileges.html#privileges-list-cluster`, elasticsearchSettings: `${ELASTICSEARCH_DOCS}security-settings.html`, + indicesPrivileges: `${ELASTICSEARCH_DOCS}security-privileges.html#privileges-list-indices`, kibanaTLS: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/configuring-tls.html`, kibanaPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/kibana-privileges.html`, - indicesPrivileges: `${ELASTICSEARCH_DOCS}security-privileges.html#privileges-list-indices`, mappingRoles: `${ELASTICSEARCH_DOCS}mapping-roles.html`, }, + watcher: { + jiraAction: `${ELASTICSEARCH_DOCS}actions-jira.html`, + pagerDutyAction: `${ELASTICSEARCH_DOCS}actions-pagerduty.html`, + slackAction: `${ELASTICSEARCH_DOCS}actions-slack.html`, + ui: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/watcher-ui.html`, + }, + ccs: { + guide: `${ELASTICSEARCH_DOCS}modules-cross-cluster-search.html`, + }, apis: { createIndex: `${ELASTICSEARCH_DOCS}indices-create-index.html`, createSnapshotLifecylePolicy: `${ELASTICSEARCH_DOCS}slm-api-put-policy.html`, @@ -189,7 +218,12 @@ export class DocLinksService { createApiKey: `${ELASTICSEARCH_DOCS}security-api-create-api-key.html`, createPipeline: `${ELASTICSEARCH_DOCS}put-pipeline-api.html`, createTransformRequest: `${ELASTICSEARCH_DOCS}put-transform.html#put-transform-request-body`, + executeWatchActionModes: `${ELASTICSEARCH_DOCS}watcher-api-execute-watch.html#watcher-api-execute-watch-action-mode`, openIndex: `${ELASTICSEARCH_DOCS}indices-open-close.html`, + putComponentTemplate: `${ELASTICSEARCH_DOCS}indices-component-template.html`, + painlessExecute: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/painless/${DOC_LINK_VERSION}/painless-execute-api.html`, + putComponentTemplateMetadata: `${ELASTICSEARCH_DOCS}indices-component-template.html#component-templates-metadata`, + putWatch: `${ELASTICSEARCH_DOCS}/watcher-api-put-watch.html`, updateTransform: `${ELASTICSEARCH_DOCS}update-transform.html`, }, }, @@ -268,6 +302,7 @@ export interface DocLinksStart { readonly sum: string; readonly top_hits: string; }; + readonly runtimeFields: string; readonly scriptedFields: { readonly scriptFields: string; readonly scriptAggs: string; @@ -282,6 +317,7 @@ export interface DocLinksStart { }; readonly addData: string; readonly kibana: string; + readonly elasticsearch: Record; readonly siem: { readonly guide: string; readonly gettingStarted: string; @@ -305,5 +341,7 @@ export interface DocLinksStart { readonly maps: Record; readonly monitoring: Record; readonly security: Record; + readonly watcher: Record; + readonly ccs: Record; }; } diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 4d00ebb213564..26ce358cc9ade 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -553,6 +553,7 @@ export interface DocLinksStart { readonly sum: string; readonly top_hits: string; }; + readonly runtimeFields: string; readonly scriptedFields: { readonly scriptFields: string; readonly scriptAggs: string; @@ -567,6 +568,7 @@ export interface DocLinksStart { }; readonly addData: string; readonly kibana: string; + readonly elasticsearch: Record; readonly siem: { readonly guide: string; readonly gettingStarted: string; @@ -590,6 +592,8 @@ export interface DocLinksStart { readonly maps: Record; readonly monitoring: Record; readonly security: Record; + readonly watcher: Record; + readonly ccs: Record; }; } From e7d0489baea87a027af47a3cbd0cf302637fc0dc Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 5 Jan 2021 06:32:34 -0800 Subject: [PATCH 22/32] Fix broken documentation link in Visualize app (#87250) --- docs/redirects.asciidoc | 5 +++++ src/core/public/doc_links/doc_links_service.ts | 2 +- src/plugins/visualize/public/application/utils/utils.ts | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index 931a783654a91..2f605f3af01b8 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -198,3 +198,8 @@ This page has moved. Refer to <>. === Variables This page has moved. Refer to <>. + +[role="exclude",id="visualize"] +== Visualize + +This page has been removed. Refer to <>. \ No newline at end of file diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 35cd58237408f..a9e55fdc22dc6 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -163,7 +163,7 @@ export class DocLinksService { guide: `${ELASTICSEARCH_DOCS}transforms.html`, }, visualize: { - guide: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/visualize.html`, + guide: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/dashboard.html`, timelionDeprecation: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/dashboard.html#timelion-deprecation`, lens: `${ELASTIC_WEBSITE_URL}what-is/kibana-lens`, maps: `${ELASTIC_WEBSITE_URL}maps`, diff --git a/src/plugins/visualize/public/application/utils/utils.ts b/src/plugins/visualize/public/application/utils/utils.ts index 3d8d443d714a5..779cfb22f7bca 100644 --- a/src/plugins/visualize/public/application/utils/utils.ts +++ b/src/plugins/visualize/public/application/utils/utils.ts @@ -31,7 +31,7 @@ export const addHelpMenuToAppChrome = (chrome: ChromeStart, docLinks: DocLinksSt links: [ { linkType: 'documentation', - href: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/visualize.html`, + href: `${docLinks.links.visualize.guide}`, }, ], }); From 6ad8a920aea0e99a5fe6b9b0990d576c24b65b8b Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Tue, 5 Jan 2021 09:42:37 -0500 Subject: [PATCH 23/32] adding docs about distinction between two and three curly braces for action variable interpolation (#87302) --- docs/user/alerting/defining-alerts.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/alerting/defining-alerts.asciidoc b/docs/user/alerting/defining-alerts.asciidoc index 667038739d45f..ffd72cc824336 100644 --- a/docs/user/alerting/defining-alerts.asciidoc +++ b/docs/user/alerting/defining-alerts.asciidoc @@ -59,7 +59,7 @@ Each action type exposes different properties. For example an email action allow [role="screenshot"] image::images/alert-flyout-action-details.png[UI for defining an email action] -Using the https://mustache.github.io/[Mustache] template syntax `{{variable name}}`, you can pass alert values at the time a condition is detected to an action. Available variables differ by alert type, and a list can be accessed using the "add variable" button. +Using the https://mustache.github.io/[Mustache] template syntax `{{variable name}}`, you can pass alert values at the time a condition is detected to an action. Note that using two curly braces will escape any HTML. Should you need to preserve HTML, use three curly braces (`{{{`). Available variables differ by alert type, and a list can be accessed using the "add variable" button. [role="screenshot"] image::images/alert-flyout-action-variables.png[Passing alert values to an action] From 86d37ae2f31b0ddb0e443b4ea79f0710be091720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Tue, 5 Jan 2021 16:23:51 +0100 Subject: [PATCH 24/32] [APM] `transactionType` should be required on service-specific endpoints (#86893) * making transaction type required on some apis * addressing PR comments Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../transaction_error_rate_chart/index.tsx | 2 +- ...se_transaction_throughput_chart_fetcher.ts | 6 +++-- ..._timeseries_data_for_transaction_groups.ts | 5 ---- .../get_service_transaction_groups/index.ts | 1 + .../merge_transaction_group_data.ts | 21 +++------------ .../get_throughput_charts/index.ts | 9 +++---- .../plugins/apm/server/routes/transactions.ts | 24 +++++------------ .../basic/tests/feature_controls.ts | 7 ----- .../basic/tests/transactions/throughput.ts | 26 +++++++++++++++---- 9 files changed, 40 insertions(+), 61 deletions(-) diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx index 3f10b572b42a3..90877a895b05b 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx @@ -36,7 +36,7 @@ export function TransactionErrorRateChart({ const { start, end, transactionName } = urlParams; const { data, status } = useFetcher(() => { - if (serviceName && start && end) { + if (transactionType && serviceName && start && end) { return callApmApi({ endpoint: 'GET /api/apm/services/{serviceName}/transactions/charts/error_rate', diff --git a/x-pack/plugins/apm/public/hooks/use_transaction_throughput_chart_fetcher.ts b/x-pack/plugins/apm/public/hooks/use_transaction_throughput_chart_fetcher.ts index c03bb8efc79b3..e030d514a5283 100644 --- a/x-pack/plugins/apm/public/hooks/use_transaction_throughput_chart_fetcher.ts +++ b/x-pack/plugins/apm/public/hooks/use_transaction_throughput_chart_fetcher.ts @@ -10,18 +10,20 @@ import { useFetcher } from './use_fetcher'; import { useUrlParams } from '../context/url_params_context/use_url_params'; import { getThrouputChartSelector } from '../selectors/throuput_chart_selectors'; import { useTheme } from './use_theme'; +import { useApmServiceContext } from '../context/apm_service/use_apm_service_context'; export function useTransactionThroughputChartsFetcher() { const { serviceName } = useParams<{ serviceName?: string }>(); + const { transactionType } = useApmServiceContext(); const theme = useTheme(); const { - urlParams: { transactionType, start, end, transactionName }, + urlParams: { start, end, transactionName }, uiFilters, } = useUrlParams(); const { data, error, status } = useFetcher( (callApmApi) => { - if (serviceName && start && end) { + if (transactionType && serviceName && start && end) { return callApmApi({ endpoint: 'GET /api/apm/services/{serviceName}/transactions/charts/throughput', diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_timeseries_data_for_transaction_groups.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_timeseries_data_for_transaction_groups.ts index 15ed46a23cae8..937155bc31602 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_timeseries_data_for_transaction_groups.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_timeseries_data_for_transaction_groups.ts @@ -87,11 +87,6 @@ export async function getTimeseriesDataForTransactionGroups({ size, }, aggs: { - transaction_types: { - terms: { - field: TRANSACTION_TYPE, - }, - }, timeseries: { date_histogram: { field: '@timestamp', diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/index.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/index.ts index 41df70c9d5429..2df4b4e4c31f5 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/index.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/index.ts @@ -80,6 +80,7 @@ export async function getServiceTransactionGroups({ start, end, latencyAggregationType, + transactionType, }), totalTransactionGroups, isAggregationAccurate, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts index 6d9fc2fd3d579..a8794e3c09a40 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts @@ -4,17 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; import { EVENT_OUTCOME } from '../../../../common/elasticsearch_fieldnames'; - -import { - TRANSACTION_PAGE_LOAD, - TRANSACTION_REQUEST, -} from '../../../../common/transaction_types'; +import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; import { getLatencyValue } from '../../helpers/latency_aggregation_type'; - import { TransactionGroupTimeseriesData } from './get_timeseries_data_for_transaction_groups'; - import { TransactionGroupWithoutTimeseriesData } from './get_transaction_groups_for_page'; export function mergeTransactionGroupData({ @@ -23,12 +16,14 @@ export function mergeTransactionGroupData({ transactionGroups, timeseriesData, latencyAggregationType, + transactionType, }: { start: number; end: number; transactionGroups: TransactionGroupWithoutTimeseriesData[]; timeseriesData: TransactionGroupTimeseriesData; latencyAggregationType: LatencyAggregationType; + transactionType: string; }) { const deltaAsMinutes = (end - start) / 1000 / 60; @@ -37,16 +32,6 @@ export function mergeTransactionGroupData({ ({ key }) => key === transactionGroup.name ); - const transactionTypes = - groupBucket?.transaction_types.buckets.map( - (bucket) => bucket.key as string - ) ?? []; - - const transactionType = - transactionTypes.find( - (type) => type === TRANSACTION_PAGE_LOAD || type === TRANSACTION_REQUEST - ) ?? transactionTypes[0]; - const timeseriesBuckets = groupBucket?.timeseries.buckets ?? []; return timeseriesBuckets.reduce( diff --git a/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts b/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts index e7007f8db0197..be374ccfe3400 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts @@ -34,7 +34,7 @@ async function searchThroughput({ intervalString, }: { serviceName: string; - transactionType: string | undefined; + transactionType: string; transactionName: string | undefined; setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; @@ -48,6 +48,7 @@ async function searchThroughput({ ...getDocumentTypeFilterForAggregatedTransactions( searchAggregatedTransactions ), + { term: { [TRANSACTION_TYPE]: transactionType } }, ...setup.esFilter, ]; @@ -55,10 +56,6 @@ async function searchThroughput({ filter.push({ term: { [TRANSACTION_NAME]: transactionName } }); } - if (transactionType) { - filter.push({ term: { [TRANSACTION_TYPE]: transactionType } }); - } - const field = getTransactionDurationFieldForAggregatedTransactions( searchAggregatedTransactions ); @@ -104,7 +101,7 @@ export async function getThroughputCharts({ searchAggregatedTransactions, }: { serviceName: string; - transactionType: string | undefined; + transactionType: string; transactionName: string | undefined; setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; diff --git a/x-pack/plugins/apm/server/routes/transactions.ts b/x-pack/plugins/apm/server/routes/transactions.ts index 12a2ea113b1a1..50510fba78512 100644 --- a/x-pack/plugins/apm/server/routes/transactions.ts +++ b/x-pack/plugins/apm/server/routes/transactions.ts @@ -35,9 +35,7 @@ export const transactionGroupsRoute = createRoute({ serviceName: t.string, }), query: t.intersection([ - t.type({ - transactionType: t.string, - }), + t.type({ transactionType: t.string }), uiFiltersRt, rangeRt, ]), @@ -199,10 +197,8 @@ export const transactionThroughputChatsRoute = createRoute({ serviceName: t.string, }), query: t.intersection([ - t.partial({ - transactionType: t.string, - transactionName: t.string, - }), + t.type({ transactionType: t.string }), + t.partial({ transactionName: t.string }), uiFiltersRt, rangeRt, ]), @@ -287,12 +283,8 @@ export const transactionChartsBreakdownRoute = createRoute({ serviceName: t.string, }), query: t.intersection([ - t.type({ - transactionType: t.string, - }), - t.partial({ - transactionName: t.string, - }), + t.type({ transactionType: t.string }), + t.partial({ transactionName: t.string }), uiFiltersRt, rangeRt, ]), @@ -322,10 +314,8 @@ export const transactionChartsErrorRateRoute = createRoute({ query: t.intersection([ uiFiltersRt, rangeRt, - t.partial({ - transactionType: t.string, - transactionName: t.string, - }), + t.type({ transactionType: t.string }), + t.partial({ transactionName: t.string }), ]), }), options: { tags: ['access:apm'] }, diff --git a/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts b/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts index 94d8f65bb6dc7..8e06dd3bda732 100644 --- a/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts +++ b/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts @@ -126,13 +126,6 @@ export default function featureControlsTests({ getService }: FtrProviderContext) expectForbidden: expect403, expectResponse: expect200, }, - { - req: { - url: `/api/apm/services/foo/transactions/charts/throughput?start=${start}&end=${end}&uiFilters=%7B%22environment%22%3A%22testing%22%7D`, - }, - expectForbidden: expect403, - expectResponse: expect200, - }, { req: { url: `/api/apm/services/foo/transactions/charts/throughput?start=${start}&end=${end}&transactionType=bar&transactionName=baz&uiFilters=%7B%22environment%22%3A%22testing%22%7D`, diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/throughput.ts b/x-pack/test/apm_api_integration/basic/tests/transactions/throughput.ts index beec346eb8d51..5a7daf8d42908 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transactions/throughput.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transactions/throughput.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import expect from '@kbn/expect'; +import url from 'url'; import archives_metadata from '../../../common/archives_metadata'; import { PromiseReturnType } from '../../../../../plugins/observability/typings/common'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -16,15 +17,22 @@ export default function ApiTest({ getService }: FtrProviderContext) { const metadata = archives_metadata[archiveName]; // url parameters - const start = encodeURIComponent(metadata.start); - const end = encodeURIComponent(metadata.end); - const uiFilters = encodeURIComponent(JSON.stringify({ environment: 'testing' })); + const { start, end } = metadata; + const uiFilters = JSON.stringify({ environment: 'testing' }); describe('Throughput', () => { describe('when data is not loaded ', () => { it('handles the empty state', async () => { const response = await supertest.get( - `/api/apm/services/opbeans-node/transactions/charts/throughput?start=${start}&end=${end}&uiFilters=${uiFilters}` + url.format({ + pathname: `/api/apm/services/opbeans-node/transactions/charts/throughput`, + query: { + start, + end, + uiFilters, + transactionType: 'request', + }, + }) ); expect(response.status).to.be(200); @@ -41,7 +49,15 @@ export default function ApiTest({ getService }: FtrProviderContext) { before(async () => { response = await supertest.get( - `/api/apm/services/opbeans-node/transactions/charts/throughput?start=${start}&end=${end}&uiFilters=${uiFilters}` + url.format({ + pathname: `/api/apm/services/opbeans-node/transactions/charts/throughput`, + query: { + start, + end, + uiFilters, + transactionType: 'request', + }, + }) ); }); From b9ff88f988ebba9d35b631ceb90e2998144efc88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Tue, 5 Jan 2021 16:24:41 +0100 Subject: [PATCH 25/32] [APM] Alert preview threshold color doesn't match design.(#86958) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../apm/public/components/alerting/chart_preview/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/apm/public/components/alerting/chart_preview/index.tsx b/x-pack/plugins/apm/public/components/alerting/chart_preview/index.tsx index 1ed5748cd757e..f01f5d21aef40 100644 --- a/x-pack/plugins/apm/public/components/alerting/chart_preview/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/chart_preview/index.tsx @@ -46,10 +46,10 @@ export function ChartPreview({ const yMax = Math.max(...values, threshold * 1.2); const style = { - fill: theme.eui.euiColorVis9, + fill: theme.eui.euiColorVis2, line: { strokeWidth: 2, - stroke: theme.eui.euiColorVis9, + stroke: theme.eui.euiColorVis2, opacity: 1, }, opacity: thresholdOpacity, From a2b4517b9e762072ca246fa3619c9acb83eb4330 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 5 Jan 2021 08:26:06 -0700 Subject: [PATCH 26/32] [data.search.session] Add extend functionality to server-side search service (#86195) * [data.search.session] Store search strategy in saved object * [data.search.session] Add extend functionality * Update docs * Update unit test to check strategy * Throw kbnServerError instead of error * Fix test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- ...gins-data-server.isearchstrategy.extend.md | 11 ++ ...gin-plugins-data-server.isearchstrategy.md | 1 + src/plugins/data/common/search/types.ts | 12 ++ .../data/server/search/search_service.ts | 14 ++ src/plugins/data/server/search/types.ts | 6 + src/plugins/data/server/server.api.md | 4 +- .../server/search/eql_search_strategy.ts | 5 + .../server/search/es_search_strategy.test.ts | 136 +++++++++++------- .../server/search/es_search_strategy.ts | 4 + 9 files changed, 143 insertions(+), 50 deletions(-) create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.extend.md diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.extend.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.extend.md new file mode 100644 index 0000000000000..65e3c2868f29f --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.extend.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchStrategy](./kibana-plugin-plugins-data-server.isearchstrategy.md) > [extend](./kibana-plugin-plugins-data-server.isearchstrategy.extend.md) + +## ISearchStrategy.extend property + +Signature: + +```typescript +extend?: (id: string, keepAlive: string, options: ISearchOptions, deps: SearchStrategyDependencies) => Promise; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.md index c9f4c886735a7..c46a580d5ceb8 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.md @@ -17,5 +17,6 @@ export interface ISearchStrategy(id: string, options: ISearchOptions, deps: SearchStrategyDependencies) => Promise<void> | | +| [extend](./kibana-plugin-plugins-data-server.isearchstrategy.extend.md) | (id: string, keepAlive: string, options: ISearchOptions, deps: SearchStrategyDependencies) => Promise<void> | | | [search](./kibana-plugin-plugins-data-server.isearchstrategy.search.md) | (request: SearchStrategyRequest, options: ISearchOptions, deps: SearchStrategyDependencies) => Observable<SearchStrategyResponse> | | diff --git a/src/plugins/data/common/search/types.ts b/src/plugins/data/common/search/types.ts index 695ee34d3b468..34e411aa85c80 100644 --- a/src/plugins/data/common/search/types.ts +++ b/src/plugins/data/common/search/types.ts @@ -29,10 +29,22 @@ export type ISearchGeneric = < ) => Observable; export type ISearchCancelGeneric = (id: string, options?: ISearchOptions) => Promise; +export type ISearchExtendGeneric = ( + id: string, + keepAlive: string, + options?: ISearchOptions +) => Promise; export interface ISearchClient { search: ISearchGeneric; + /** + * Used to cancel an in-progress search request. + */ cancel: ISearchCancelGeneric; + /** + * Used to extend the TTL of an in-progress search request. + */ + extend: ISearchExtendGeneric; } export interface IKibanaSearchResponse { diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts index 5de019cd1b83e..d26c099b23f39 100644 --- a/src/plugins/data/server/search/search_service.ts +++ b/src/plugins/data/server/search/search_service.ts @@ -315,6 +315,19 @@ export class SearchService implements Plugin { return strategy.cancel(id, options, deps); }; + private extend = ( + id: string, + keepAlive: string, + options: ISearchOptions, + deps: SearchStrategyDependencies + ) => { + const strategy = this.getSearchStrategy(options.strategy); + if (!strategy.extend) { + throw new KbnServerError(`Search strategy ${options.strategy} does not support extend`, 400); + } + return strategy.extend(id, keepAlive, options, deps); + }; + private getSearchStrategy = < SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse @@ -344,6 +357,7 @@ export class SearchService implements Plugin { search: (searchRequest, options = {}) => this.search(scopedSession, searchRequest, options, deps), cancel: (id, options = {}) => this.cancel(id, options, deps), + extend: (id, keepAlive, options = {}) => this.extend(id, keepAlive, options, deps), }; }; }; diff --git a/src/plugins/data/server/search/types.ts b/src/plugins/data/server/search/types.ts index db8b8ac72d0e5..fb00f86464e4e 100644 --- a/src/plugins/data/server/search/types.ts +++ b/src/plugins/data/server/search/types.ts @@ -86,6 +86,12 @@ export interface ISearchStrategy< deps: SearchStrategyDependencies ) => Observable; cancel?: (id: string, options: ISearchOptions, deps: SearchStrategyDependencies) => Promise; + extend?: ( + id: string, + keepAlive: string, + options: ISearchOptions, + deps: SearchStrategyDependencies + ) => Promise; } export interface ISearchStart< diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index cd3527d5ad7ab..bb8ed92e9bfce 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -952,6 +952,8 @@ export interface ISearchStrategy Promise; // (undocumented) + extend?: (id: string, keepAlive: string, options: ISearchOptions, deps: SearchStrategyDependencies) => Promise; + // (undocumented) search: (request: SearchStrategyRequest, options: ISearchOptions, deps: SearchStrategyDependencies) => Observable; } @@ -1430,7 +1432,7 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:279:1 - (ae-forgotten-export) The symbol "calcAutoIntervalLessThan" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index_patterns/index_patterns_service.ts:70:14 - (ae-forgotten-export) The symbol "IndexPatternsService" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:90:74 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/search/types.ts:106:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/search/types.ts:112:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/x-pack/plugins/data_enhanced/server/search/eql_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/eql_search_strategy.ts index 26325afc378f7..e615d9d2a660a 100644 --- a/x-pack/plugins/data_enhanced/server/search/eql_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/eql_search_strategy.ts @@ -56,5 +56,10 @@ export const eqlSearchStrategyProvider = ( return pollSearch(search, options).pipe(tap((response) => (id = response.id))); }, + + extend: async (id, keepAlive, options, { esClient }) => { + logger.debug(`_eql/extend ${id} by ${keepAlive}`); + await esClient.asCurrentUser.eql.get({ id, keep_alive: keepAlive }); + }, }; }; diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts index b9b6e25067f2f..3230895da7705 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts @@ -37,6 +37,7 @@ describe('ES search strategy', () => { const mockApiCaller = jest.fn(); const mockGetCaller = jest.fn(); const mockSubmitCaller = jest.fn(); + const mockDeleteCaller = jest.fn(); const mockLogger: any = { debug: () => {}, }; @@ -49,6 +50,7 @@ describe('ES search strategy', () => { asyncSearch: { get: mockGetCaller, submit: mockSubmitCaller, + delete: mockDeleteCaller, }, transport: { request: mockApiCaller }, }, @@ -66,77 +68,113 @@ describe('ES search strategy', () => { beforeEach(() => { mockApiCaller.mockClear(); + mockGetCaller.mockClear(); + mockSubmitCaller.mockClear(); + mockDeleteCaller.mockClear(); }); - it('returns a strategy with `search`', async () => { + it('returns a strategy with `search and `cancel`', async () => { const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$, mockLogger); expect(typeof esSearch.search).toBe('function'); }); - it('makes a POST request to async search with params when no ID is provided', async () => { - mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); + describe('search', () => { + it('makes a POST request to async search with params when no ID is provided', async () => { + mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); - const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$, mockLogger); + const params = { index: 'logstash-*', body: { query: {} } }; + const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$, mockLogger); - await esSearch.search({ params }, {}, mockDeps).toPromise(); + await esSearch.search({ params }, {}, mockDeps).toPromise(); - expect(mockSubmitCaller).toBeCalled(); - const request = mockSubmitCaller.mock.calls[0][0]; - expect(request.index).toEqual(params.index); - expect(request.body).toEqual(params.body); - }); + expect(mockSubmitCaller).toBeCalled(); + const request = mockSubmitCaller.mock.calls[0][0]; + expect(request.index).toEqual(params.index); + expect(request.body).toEqual(params.body); + }); - it('makes a GET request to async search with ID when ID is provided', async () => { - mockGetCaller.mockResolvedValueOnce(mockAsyncResponse); + it('makes a GET request to async search with ID when ID is provided', async () => { + mockGetCaller.mockResolvedValueOnce(mockAsyncResponse); - const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$, mockLogger); + const params = { index: 'logstash-*', body: { query: {} } }; + const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$, mockLogger); + + await esSearch.search({ id: 'foo', params }, {}, mockDeps).toPromise(); + + expect(mockGetCaller).toBeCalled(); + const request = mockGetCaller.mock.calls[0][0]; + expect(request.id).toEqual('foo'); + expect(request).toHaveProperty('wait_for_completion_timeout'); + expect(request).toHaveProperty('keep_alive'); + }); + + it('calls the rollup API if the index is a rollup type', async () => { + mockApiCaller.mockResolvedValueOnce(mockRollupResponse); + + const params = { index: 'foo-程', body: {} }; + const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$, mockLogger); + + await esSearch + .search( + { + indexType: 'rollup', + params, + }, + {}, + mockDeps + ) + .toPromise(); - await esSearch.search({ id: 'foo', params }, {}, mockDeps).toPromise(); + expect(mockApiCaller).toBeCalled(); + const { method, path } = mockApiCaller.mock.calls[0][0]; + expect(method).toBe('POST'); + expect(path).toBe('/foo-%E7%A8%8B/_rollup_search'); + }); - expect(mockGetCaller).toBeCalled(); - const request = mockGetCaller.mock.calls[0][0]; - expect(request.id).toEqual('foo'); - expect(request).toHaveProperty('wait_for_completion_timeout'); - expect(request).toHaveProperty('keep_alive'); + it('sets wait_for_completion_timeout and keep_alive in the request', async () => { + mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); + + const params = { index: 'foo-*', body: {} }; + const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$, mockLogger); + + await esSearch.search({ params }, {}, mockDeps).toPromise(); + + expect(mockSubmitCaller).toBeCalled(); + const request = mockSubmitCaller.mock.calls[0][0]; + expect(request).toHaveProperty('wait_for_completion_timeout'); + expect(request).toHaveProperty('keep_alive'); + }); }); - it('calls the rollup API if the index is a rollup type', async () => { - mockApiCaller.mockResolvedValueOnce(mockRollupResponse); + describe('cancel', () => { + it('makes a DELETE request to async search with the provided ID', async () => { + mockDeleteCaller.mockResolvedValueOnce(200); - const params = { index: 'foo-程', body: {} }; - const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$, mockLogger); + const id = 'some_id'; + const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$, mockLogger); - await esSearch - .search( - { - indexType: 'rollup', - params, - }, - {}, - mockDeps - ) - .toPromise(); - - expect(mockApiCaller).toBeCalled(); - const { method, path } = mockApiCaller.mock.calls[0][0]; - expect(method).toBe('POST'); - expect(path).toBe('/foo-%E7%A8%8B/_rollup_search'); + await esSearch.cancel!(id, {}, mockDeps); + + expect(mockDeleteCaller).toBeCalled(); + const request = mockDeleteCaller.mock.calls[0][0]; + expect(request).toEqual({ id }); + }); }); - it('sets wait_for_completion_timeout and keep_alive in the request', async () => { - mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); + describe('extend', () => { + it('makes a GET request to async search with the provided ID and keepAlive', async () => { + mockGetCaller.mockResolvedValueOnce(mockAsyncResponse); - const params = { index: 'foo-*', body: {} }; - const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$, mockLogger); + const id = 'some_other_id'; + const keepAlive = '1d'; + const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$, mockLogger); - await esSearch.search({ params }, {}, mockDeps).toPromise(); + await esSearch.extend!(id, keepAlive, {}, mockDeps); - expect(mockSubmitCaller).toBeCalled(); - const request = mockSubmitCaller.mock.calls[0][0]; - expect(request).toHaveProperty('wait_for_completion_timeout'); - expect(request).toHaveProperty('keep_alive'); + expect(mockGetCaller).toBeCalled(); + const request = mockGetCaller.mock.calls[0][0]; + expect(request).toEqual({ id, keep_alive: keepAlive }); + }); }); }); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index fc5787f9e5cab..c1520d931c272 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -111,5 +111,9 @@ export const enhancedEsSearchStrategyProvider = ( logger.debug(`cancel ${id}`); await esClient.asCurrentUser.asyncSearch.delete({ id }); }, + extend: async (id, keepAlive, options, { esClient }) => { + logger.debug(`extend ${id} by ${keepAlive}`); + await esClient.asCurrentUser.asyncSearch.get({ id, keep_alive: keepAlive }); + }, }; }; From ff94674919035fceb67522d87dc851b5e181fcaa Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Tue, 5 Jan 2021 08:32:39 -0700 Subject: [PATCH 27/32] Use new es client in Uptime usage collector (#86718) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../telemetry/kibana_telemetry_adapter.ts | 28 ++++++------------- x-pack/plugins/uptime/server/lib/lib.ts | 9 ++++-- .../typings/elasticsearch/aggregations.d.ts | 8 ++++++ 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts b/x-pack/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts index 3f6c3da2d6af0..8922661ec0504 100644 --- a/x-pack/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts +++ b/x-pack/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts @@ -5,29 +5,21 @@ */ import moment from 'moment'; -import { - ISavedObjectsRepository, - ILegacyScopedClusterClient, - SavedObjectsClientContract, - ElasticsearchClient, -} from 'kibana/server'; +import { ISavedObjectsRepository, SavedObjectsClientContract } from 'kibana/server'; import { CollectorFetchContext, UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { PageViewParams, UptimeTelemetry, Usage } from './types'; import { savedObjectsAdapter } from '../../saved_objects'; -import { UptimeESClient } from '../../lib'; +import { UptimeESClient, createUptimeESClient } from '../../lib'; interface UptimeTelemetryCollector { [key: number]: UptimeTelemetry; } - // seconds in an hour const BUCKET_SIZE = 3600; // take buckets in the last day const BUCKET_NUMBER = 24; export class KibanaTelemetryAdapter { - public static callCluster: ILegacyScopedClusterClient['callAsCurrentUser'] | ElasticsearchClient; - public static registerUsageCollector = ( usageCollector: UsageCollectionSetup, getSavedObjectsClient: () => ISavedObjectsRepository | undefined @@ -76,10 +68,11 @@ export class KibanaTelemetryAdapter { }, }, }, - fetch: async ({ callCluster }: CollectorFetchContext) => { + fetch: async ({ esClient }: CollectorFetchContext) => { const savedObjectsClient = getSavedObjectsClient()!; if (savedObjectsClient) { - await this.countNoOfUniqueMonitorAndLocations(callCluster, savedObjectsClient); + const uptimeEsClient = createUptimeESClient({ esClient, savedObjectsClient }); + await this.countNoOfUniqueMonitorAndLocations(uptimeEsClient, savedObjectsClient); } const report = this.getReport(); return { last_24_hours: { hits: { ...report } } }; @@ -132,7 +125,7 @@ export class KibanaTelemetryAdapter { } public static async countNoOfUniqueMonitorAndLocations( - callCluster: ILegacyScopedClusterClient['callAsCurrentUser'] | UptimeESClient, + callCluster: UptimeESClient, savedObjectsClient: ISavedObjectsRepository | SavedObjectsClientContract ) { const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings(savedObjectsClient); @@ -194,15 +187,12 @@ export class KibanaTelemetryAdapter { }, }; - const { body: result } = - typeof callCluster === 'function' - ? await callCluster('search', params) - : await callCluster.search(params); + const { body: result } = await callCluster.search(params); const numberOfUniqueMonitors: number = result?.aggregations?.unique_monitors?.value ?? 0; const numberOfUniqueLocations: number = result?.aggregations?.unique_locations?.value ?? 0; - const monitorNameStats: any = result?.aggregations?.monitor_name; - const locationNameStats: any = result?.aggregations?.observer_loc_name; + const monitorNameStats = result?.aggregations?.monitor_name; + const locationNameStats = result?.aggregations?.observer_loc_name; const uniqueMonitors: any = result?.aggregations?.monitors.buckets; const bucketId = this.getBucketToIncrement(); diff --git a/x-pack/plugins/uptime/server/lib/lib.ts b/x-pack/plugins/uptime/server/lib/lib.ts index ee84cf4463ceb..6515bdce31c69 100644 --- a/x-pack/plugins/uptime/server/lib/lib.ts +++ b/x-pack/plugins/uptime/server/lib/lib.ts @@ -3,7 +3,12 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { ElasticsearchClient, SavedObjectsClientContract, KibanaRequest } from 'kibana/server'; +import { + ElasticsearchClient, + SavedObjectsClientContract, + KibanaRequest, + ISavedObjectsRepository, +} from 'kibana/server'; import chalk from 'chalk'; import { UMBackendFrameworkAdapter } from './adapters'; import { UMLicenseCheck } from './domains'; @@ -41,7 +46,7 @@ export function createUptimeESClient({ }: { esClient: ElasticsearchClient; request?: KibanaRequest; - savedObjectsClient: SavedObjectsClientContract; + savedObjectsClient: SavedObjectsClientContract | ISavedObjectsRepository; }) { const { _debug = false } = (request?.query as { _debug: boolean }) ?? {}; diff --git a/x-pack/typings/elasticsearch/aggregations.d.ts b/x-pack/typings/elasticsearch/aggregations.d.ts index 12542363fa8e8..9f25920353b2f 100644 --- a/x-pack/typings/elasticsearch/aggregations.d.ts +++ b/x-pack/typings/elasticsearch/aggregations.d.ts @@ -99,6 +99,7 @@ export interface AggregationOptionsByType { extended_stats: { field: string; }; + string_stats: { field: string }; top_hits: { from?: number; size?: number; @@ -274,6 +275,13 @@ interface AggregationResponsePart Date: Tue, 5 Jan 2021 16:07:04 +0000 Subject: [PATCH 28/32] [Security Solution] JSON view for data is not displayed properly (#87008) --- .../__snapshots__/event_details.test.tsx.snap | 1332 ----------------- .../event_details/event_details.test.tsx | 8 +- .../event_details/event_details.tsx | 9 +- .../events_viewer/event_details_flyout.tsx | 18 +- .../timeline/expandable_event/index.tsx | 39 +- 5 files changed, 50 insertions(+), 1356 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/event_details.test.tsx.snap diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/event_details.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/event_details.test.tsx.snap deleted file mode 100644 index e9b11d9bcdf71..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/event_details.test.tsx.snap +++ /dev/null @@ -1,1332 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`EventDetails rendering should match snapshot 1`] = ` - - - - , - "id": "table-view", - "name": "Table", - } - } - tabs={ - Array [ - Object { - "content": - - - , - "id": "table-view", - "name": "Table", - }, - Object { - "content": - - - , - "id": "json-view", - "name": "JSON View", - }, - ] - } -/> -`; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx index 9ab286b120dd3..4bd3ae126e9dc 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx @@ -5,7 +5,7 @@ */ import { waitFor } from '@testing-library/dom'; -import { ReactWrapper, shallow } from 'enzyme'; +import { ReactWrapper } from 'enzyme'; import React from 'react'; import '../../mock/match_media'; @@ -54,12 +54,6 @@ describe('EventDetails', () => { ) as ReactWrapper; await waitFor(() => wrapper.update()); }); - describe('rendering', () => { - test('should match snapshot', () => { - const shallowWrap = shallow(); - expect(shallowWrap).toMatchSnapshot(); - }); - }); describe('tabs', () => { ['Table', 'JSON View'].forEach((tab) => { diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx index 123a3fa7b610b..0a8046e461d20 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.tsx @@ -48,6 +48,11 @@ const StyledEuiTabbedContent = styled(EuiTabbedContent)` } `; +const TabContentWrapper = styled.div` + height: 100%; + position: relative; +`; + const EventDetailsComponent: React.FC = ({ browserFields, data, @@ -105,7 +110,9 @@ const EventDetailsComponent: React.FC = ({ content: ( <> - + + + ), }, diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/event_details_flyout.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/event_details_flyout.tsx index 9c09f2e696104..72ec918fd0577 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/event_details_flyout.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/event_details_flyout.tsx @@ -25,6 +25,20 @@ const StyledEuiFlyout = styled(EuiFlyout)` z-index: ${({ theme }) => theme.eui.euiZLevel7}; `; +const StyledEuiFlyoutBody = styled(EuiFlyoutBody)` + .euiFlyoutBody__overflow { + display: flex; + flex: 1; + overflow: hidden; + + .euiFlyoutBody__overflowContent { + flex: 1; + overflow: hidden; + padding: ${({ theme }) => `${theme.eui.paddingSizes.xs} ${theme.eui.paddingSizes.m} 64px`}; + } + } +`; + interface EventDetailsFlyoutProps { browserFields: BrowserFields; docValueFields: DocValueFields[]; @@ -67,7 +81,7 @@ const EventDetailsFlyoutComponent: React.FC = ({ - + = ({ timelineId={timelineId} timelineTabType="flyout" /> - + ); }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/expandable_event/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/expandable_event/index.tsx index a38fde0e3f548..27d28aa525d56 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/expandable_event/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/expandable_event/index.tsx @@ -38,6 +38,7 @@ interface Props { event: TimelineExpandedEventType; isAlert: boolean; loading: boolean; + messageHeight?: number; timelineTabType: TimelineTabs | 'flyout'; timelineId: string; } @@ -52,6 +53,14 @@ const StyledEuiFlexGroup = styled(EuiFlexGroup)` flex: 0; `; +const StyledFlexGroup = styled(EuiFlexGroup)` + height: 100%; +`; + +const StyledEuiFlexItem = styled(EuiFlexItem)` + overflow: hidden; +`; + export const ExpandableEventTitle = React.memo( ({ isAlert, loading, handleOnEventClosed }) => ( @@ -99,9 +108,9 @@ export const ExpandableEvent = React.memo( } return ( - <> + {message && ( - <> + {i18n.MESSAGE} @@ -109,19 +118,21 @@ export const ExpandableEvent = React.memo( - + )} - - + + + + ); } ); From c69eaf872aba7617f1565f22438ad98227c57ade Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Tue, 5 Jan 2021 10:12:03 -0600 Subject: [PATCH 29/32] [Workplace Search] Move Personal Dashboard link to header (#87244) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove comment We aren’t going to use icons like we have in ent-search * Add new constant * Use constant instead of inline i18n * Add link to top bar The external href to sources will be changed once that component is built * Remove link from sidebar * Update i18n translation key names CI was failing and this should fix it * Alphabetize items --- .../layout/kibana_header_actions.test.tsx | 14 ++++- .../layout/kibana_header_actions.tsx | 33 +++++++----- .../components/layout/nav.test.tsx | 2 +- .../components/layout/nav.tsx | 52 ++++++++----------- .../workplace_search/constants.ts | 3 ++ .../translations/translations/ja-JP.json | 2 +- .../translations/translations/zh-CN.json | 2 +- 7 files changed, 62 insertions(+), 46 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx index 0ebd59eda5be7..60689242ab882 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.test.tsx @@ -19,11 +19,23 @@ describe('WorkplaceSearchHeaderActions', () => { expect(wrapper.isEmptyRender()).toBe(true); }); + it('renders a link to the personal dashboard', () => { + externalUrl.enterpriseSearchUrl = 'http://localhost:3002'; + + const wrapper = shallow(); + + expect(wrapper.find(EuiButtonEmpty).first().prop('href')).toEqual( + 'http://localhost:3002/ws/sources' + ); + }); + it('renders a link to the search application', () => { externalUrl.enterpriseSearchUrl = 'http://localhost:3002'; const wrapper = shallow(); - expect(wrapper.find(EuiButtonEmpty).prop('href')).toEqual('http://localhost:3002/ws/search'); + expect(wrapper.find(EuiButtonEmpty).last().prop('href')).toEqual( + 'http://localhost:3002/ws/search' + ); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx index fe73098f044c0..c3e5f0f24a299 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/kibana_header_actions.tsx @@ -5,26 +5,33 @@ */ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty, EuiText } from '@elastic/eui'; import { externalUrl, getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; +import { NAV } from '../../constants'; + export const WorkplaceSearchHeaderActions: React.FC = () => { if (!externalUrl.enterpriseSearchUrl) return null; return ( - - - {i18n.translate('xpack.enterpriseSearch.workplaceSearch.headerActions.searchApplication', { - defaultMessage: 'Go to search application', - })} - - + <> + + {NAV.PERSONAL_DASHBOARD} + + + {NAV.SEARCH} + + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx index ccc0fe8b38ff3..3cfdb5b13de5b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx @@ -18,6 +18,6 @@ describe('WorkplaceSearchNav', () => { expect(wrapper.find(SideNav)).toHaveLength(1); expect(wrapper.find(SideNavLink).first().prop('to')).toEqual('/'); - expect(wrapper.find(SideNavLink)).toHaveLength(7); + expect(wrapper.find(SideNavLink)).toHaveLength(6); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx index de6c75d60189e..944820c4b1c40 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx @@ -26,32 +26,26 @@ interface Props { groupsSubNav?: React.ReactNode; } -export const WorkplaceSearchNav: React.FC = ({ sourcesSubNav, groupsSubNav }) => { - // TODO: icons - return ( - - - {NAV.OVERVIEW} - - - {NAV.SOURCES} - - - {NAV.GROUPS} - - - {NAV.ROLE_MAPPINGS} - - - {NAV.SECURITY} - - - {NAV.SETTINGS} - - - - {NAV.PERSONAL_DASHBOARD} - - - ); -}; +export const WorkplaceSearchNav: React.FC = ({ sourcesSubNav, groupsSubNav }) => ( + + + {NAV.OVERVIEW} + + + {NAV.SOURCES} + + + {NAV.GROUPS} + + + {NAV.ROLE_MAPPINGS} + + + {NAV.SECURITY} + + + {NAV.SETTINGS} + + + +); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts index 3e828d0fe80de..74e0682db89b5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts @@ -52,6 +52,9 @@ export const NAV = { defaultMessage: 'View my personal dashboard', } ), + SEARCH: i18n.translate('xpack.enterpriseSearch.workplaceSearch.nav.searchApplication', { + defaultMessage: 'Go to search application', + }), }; export const MAX_TABLE_ROW_ICONS = 3; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 116a81361699f..59e69ca1b1f68 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6964,13 +6964,13 @@ "xpack.enterpriseSearch.workplaceSearch.groups.sourcesModalTitle": "{groupName}と共有するコンテンツソースを選択", "xpack.enterpriseSearch.workplaceSearch.groups.userListCount": "{maxVisibleUsers}/{numUsers}ユーザーを表示しています。", "xpack.enterpriseSearch.workplaceSearch.groups.usersModalLabel": "ユーザー", - "xpack.enterpriseSearch.workplaceSearch.headerActions.searchApplication": "検索アプリケーションに移動", "xpack.enterpriseSearch.workplaceSearch.nav.groups": "グループ", "xpack.enterpriseSearch.workplaceSearch.nav.groups.groupOverview": "概要", "xpack.enterpriseSearch.workplaceSearch.nav.groups.sourcePrioritization": "ソースの優先度", "xpack.enterpriseSearch.workplaceSearch.nav.overview": "概要", "xpack.enterpriseSearch.workplaceSearch.nav.personalDashboard": "個人のダッシュボードを表示", "xpack.enterpriseSearch.workplaceSearch.nav.roleMappings": "ロールマッピング", + "xpack.enterpriseSearch.workplaceSearch.nav.searchApplication": "検索アプリケーションに移動", "xpack.enterpriseSearch.workplaceSearch.nav.security": "セキュリティ", "xpack.enterpriseSearch.workplaceSearch.nav.settings": "設定", "xpack.enterpriseSearch.workplaceSearch.nav.sources": "ソース", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index f03b720c8a77f..f1d22fb7c84f5 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6970,13 +6970,13 @@ "xpack.enterpriseSearch.workplaceSearch.groups.sourcesModalTitle": "选择要与 {groupName} 共享的内容源", "xpack.enterpriseSearch.workplaceSearch.groups.userListCount": "正在显示 {numUsers} 个用户中的 {maxVisibleUsers} 个。", "xpack.enterpriseSearch.workplaceSearch.groups.usersModalLabel": "用户", - "xpack.enterpriseSearch.workplaceSearch.headerActions.searchApplication": "前往搜索应用程序", "xpack.enterpriseSearch.workplaceSearch.nav.groups": "组", "xpack.enterpriseSearch.workplaceSearch.nav.groups.groupOverview": "概览", "xpack.enterpriseSearch.workplaceSearch.nav.groups.sourcePrioritization": "源的优先级排序", "xpack.enterpriseSearch.workplaceSearch.nav.overview": "概览", "xpack.enterpriseSearch.workplaceSearch.nav.personalDashboard": "查看我的个人仪表板", "xpack.enterpriseSearch.workplaceSearch.nav.roleMappings": "角色映射", + "xpack.enterpriseSearch.workplaceSearch.nav.searchApplication": "前往搜索应用程序", "xpack.enterpriseSearch.workplaceSearch.nav.security": "安全", "xpack.enterpriseSearch.workplaceSearch.nav.settings": "设置", "xpack.enterpriseSearch.workplaceSearch.nav.sources": "源", From 24748bff779def687fdda97ffda4493d59c2641d Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Tue, 5 Jan 2021 10:12:49 -0600 Subject: [PATCH 30/32] [Workplace Search] Add routes for settings (#87239) --- .../server/routes/workplace_search/index.ts | 2 + .../routes/workplace_search/settings.test.ts | 114 ++++++++++++++++++ .../routes/workplace_search/settings.ts | 80 ++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 x-pack/plugins/enterprise_search/server/routes/workplace_search/settings.test.ts create mode 100644 x-pack/plugins/enterprise_search/server/routes/workplace_search/settings.ts diff --git a/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts b/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts index 1df7a1d6875a6..99445108b315a 100644 --- a/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts +++ b/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts @@ -9,9 +9,11 @@ import { RouteDependencies } from '../../plugin'; import { registerOverviewRoute } from './overview'; import { registerGroupsRoutes } from './groups'; import { registerSourcesRoutes } from './sources'; +import { registerSettingsRoutes } from './settings'; export const registerWorkplaceSearchRoutes = (dependencies: RouteDependencies) => { registerOverviewRoute(dependencies); registerGroupsRoutes(dependencies); registerSourcesRoutes(dependencies); + registerSettingsRoutes(dependencies); }; diff --git a/x-pack/plugins/enterprise_search/server/routes/workplace_search/settings.test.ts b/x-pack/plugins/enterprise_search/server/routes/workplace_search/settings.test.ts new file mode 100644 index 0000000000000..932bf5e3685e6 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/routes/workplace_search/settings.test.ts @@ -0,0 +1,114 @@ +/* + * 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 { MockRouter, mockRequestHandler, mockDependencies } from '../../__mocks__'; + +import { + registerOrgSettingsRoute, + registerOrgSettingsCustomizeRoute, + registerOrgSettingsOauthApplicationRoute, +} from './settings'; + +describe('settings routes', () => { + describe('GET /api/workplace_search/org/settings', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('creates a request handler', () => { + mockRouter = new MockRouter({ + method: 'get', + path: '/api/workplace_search/org/settings', + payload: 'params', + }); + + registerOrgSettingsRoute({ + ...mockDependencies, + router: mockRouter.router, + }); + + mockRouter.callRoute({}); + + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/ws/org/settings', + }); + }); + }); + + describe('PUT /api/workplace_search/org/settings/customize', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('creates a request handler', () => { + mockRouter = new MockRouter({ + method: 'put', + path: '/api/workplace_search/org/settings/customize', + payload: 'body', + }); + + registerOrgSettingsCustomizeRoute({ + ...mockDependencies, + router: mockRouter.router, + }); + + const mockRequest = { + body: { + name: 'foo', + }, + }; + + mockRouter.callRoute(mockRequest); + + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/ws/org/settings/customize', + body: mockRequest.body, + }); + }); + }); + + describe('PUT /api/workplace_search/org/settings/oauth_application', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('creates a request handler', () => { + mockRouter = new MockRouter({ + method: 'put', + path: '/api/workplace_search/org/settings/oauth_application', + payload: 'body', + }); + + registerOrgSettingsOauthApplicationRoute({ + ...mockDependencies, + router: mockRouter.router, + }); + + const mockRequest = { + body: { + oauth_application: { + name: 'foo', + confidential: true, + redirect_uri: 'http://foo.bar', + }, + }, + }; + + mockRouter.callRoute(mockRequest); + + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/ws/org/settings/oauth_application', + body: mockRequest.body, + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/routes/workplace_search/settings.ts b/x-pack/plugins/enterprise_search/server/routes/workplace_search/settings.ts new file mode 100644 index 0000000000000..cdba6609eb871 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/routes/workplace_search/settings.ts @@ -0,0 +1,80 @@ +/* + * 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 { schema } from '@kbn/config-schema'; + +import { RouteDependencies } from '../../plugin'; + +export function registerOrgSettingsRoute({ + router, + enterpriseSearchRequestHandler, +}: RouteDependencies) { + router.get( + { + path: '/api/workplace_search/org/settings', + validate: false, + }, + async (context, request, response) => { + return enterpriseSearchRequestHandler.createRequest({ + path: '/ws/org/settings', + })(context, request, response); + } + ); +} + +export function registerOrgSettingsCustomizeRoute({ + router, + enterpriseSearchRequestHandler, +}: RouteDependencies) { + router.put( + { + path: '/api/workplace_search/org/settings/customize', + validate: { + body: schema.object({ + name: schema.string(), + }), + }, + }, + async (context, request, response) => { + return enterpriseSearchRequestHandler.createRequest({ + path: '/ws/org/settings/customize', + body: request.body, + })(context, request, response); + } + ); +} + +export function registerOrgSettingsOauthApplicationRoute({ + router, + enterpriseSearchRequestHandler, +}: RouteDependencies) { + router.put( + { + path: '/api/workplace_search/org/settings/oauth_application', + validate: { + body: schema.object({ + oauth_application: schema.object({ + name: schema.string(), + confidential: schema.boolean(), + redirect_uri: schema.string(), + }), + }), + }, + }, + async (context, request, response) => { + return enterpriseSearchRequestHandler.createRequest({ + path: '/ws/org/settings/oauth_application', + body: request.body, + })(context, request, response); + } + ); +} + +export const registerSettingsRoutes = (dependencies: RouteDependencies) => { + registerOrgSettingsRoute(dependencies); + registerOrgSettingsCustomizeRoute(dependencies); + registerOrgSettingsOauthApplicationRoute(dependencies); +}; From 0c41c2d598d0034cd7d6d5c68ea7c22de3273555 Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Tue, 5 Jan 2021 11:26:47 -0500 Subject: [PATCH 31/32] Update security docs (#87215) --- .../managing-saved-objects.asciidoc | 8 +-- .../securing-communications/index.asciidoc | 52 +++++++++---------- docs/user/security/securing-kibana.asciidoc | 44 +++++++--------- 3 files changed, 50 insertions(+), 54 deletions(-) diff --git a/docs/management/managing-saved-objects.asciidoc b/docs/management/managing-saved-objects.asciidoc index 2e081c09e0e70..9e26abca115fc 100644 --- a/docs/management/managing-saved-objects.asciidoc +++ b/docs/management/managing-saved-objects.asciidoc @@ -60,8 +60,8 @@ You have two options for exporting saved objects. * Select the checkboxes of objects that you want to export, and then click *Export*. * Click *Export x objects*, and export objects by type. -This action creates an NDJSON with all your saved objects. By default, -the NDJSON includes related objects. Exported dashboards include their associated index patterns. +This action creates an NDJSON with all your saved objects. By default, the NDJSON includes child objects that are related to the saved +objects. Exported dashboards include their associated index patterns. [float] [role="xpack"] @@ -73,8 +73,8 @@ and select *Copy to space*. From here, you can select the spaces in which to cop You can also select whether to automatically overwrite any conflicts in the target spaces, or resolve them manually. -WARNING: The copy operation automatically includes related objects. If you don't want this behavior, -use the <> instead. +WARNING: The copy operation automatically includes child objects that are related to the saved objects. If you don't want this behavior, use +the <> instead. [float] diff --git a/docs/user/security/securing-communications/index.asciidoc b/docs/user/security/securing-communications/index.asciidoc index 0509c6b13d54a..706c15fe6ec0f 100644 --- a/docs/user/security/securing-communications/index.asciidoc +++ b/docs/user/security/securing-communications/index.asciidoc @@ -26,65 +26,65 @@ NOTE: You do not need to enable the {es} {security-features} for this type of en When you obtain a server certificate, you must set its subject alternative name (SAN) correctly to ensure that modern web browsers with hostname verification will trust it. You can set one or more SANs to the {kib} server's fully-qualified domain name (FQDN), hostname, or IP address. When choosing the SAN, you should pick whichever attribute you will be using to connect to {kib} in your browser, which is likely -the FQDN. +the FQDN in a production environment. - -You may choose to generate a certificate signing request (CSR) and private key using the {ref}/certutil.html[`elasticsearch-certutil`] tool. +You may choose to generate a signed certificate and private key using the {ref}/certutil.html[`elasticsearch-certutil`] tool. For example: [source,sh] -------------------------------------------------------------------------------- -bin/elasticsearch-certutil csr -name kibana-server -dns some-website.com,www.some-website.com +bin/elasticsearch-certutil cert -name kibana-server -dns localhost,127.0.0.1 -------------------------------------------------------------------------------- -This will produce a ZIP archive named `kibana-server.zip`. Extract that archive to obtain the PEM-formatted CSR (`kibana-server.csr`) and -unencrypted private key (`kibana-server.key`). In this example, the CSR has a common name (CN) of `kibana-server`, a SAN of -`some-website.com`, and another SAN of `www.some-website.com`. +This will produce a PKCS#12 file named `kibana-server.p12`, which contains the server certificate and private key. -NOTE: You will need to use a certificate authority (CA) to sign your CSR to obtain your server certificate. This certificate's signature -will be verified by web browsers that are configured to trust the CA. +NOTE: In this example, the server certificate is signed by a locally-generated certificate authority (CA). This is not suitable for a +production environment, and it will result in warnings in your web browser until you configure your browser to trust the certificate. Steps +to configure certificate trust vary depending upon your browser and operating system. If you want to obtain a server certificate for a +production environment, you can instead generate a certificate signing request (CSR) with `elasticsearch-certutil` using +{ref}/certutil.html#certutil-csr[CSR mode]. -- . Configure {kib} to access the server certificate and private key. -.. If your server certificate and private key are in PEM format: +.. If your server certificate and private key are contained in a PKCS#12 file: + -- -Specify your server certificate and private key in `kibana.yml`: +Specify your PKCS#12 file in `kibana.yml`: [source,yaml] -------------------------------------------------------------------------------- -server.ssl.certificate: "/path/to/kibana-server.crt" -server.ssl.key: "/path/to/kibana-server.key" +server.ssl.keystore.path: "/path/to/kibana-server.p12" -------------------------------------------------------------------------------- -If your private key is encrypted, add the decryption password to your <>: +If your PKCS#12 file is encrypted, add the decryption password to your <>: [source,yaml] -------------------------------------------------------------------------------- -bin/kibana-keystore add server.ssl.keyPassphrase +bin/kibana-keystore add server.ssl.keystore.password -------------------------------------------------------------------------------- + +NOTE: If you used `elasticsearch-certutil` to generate a PKCS#12 file and you did not specify a password, the file is encrypted, and you +need to set `server.ssl.keystore.password` to an empty string. -- -.. Otherwise, if your server certificate and private key are contained in a PKCS#12 file: +.. Otherwise, if your server certificate and private key are in PEM format: + -- -Specify your PKCS#12 file in `kibana.yml`: +Specify your server certificate and private key in `kibana.yml`: [source,yaml] -------------------------------------------------------------------------------- -server.ssl.keystore.path: "/path/to/kibana-server.p12" +server.ssl.certificate: "/path/to/kibana-server.crt" +server.ssl.key: "/path/to/kibana-server.key" -------------------------------------------------------------------------------- -If your PKCS#12 file is encrypted, add the decryption password to your <>: +If your private key is encrypted, add the decryption password to your <>: [source,yaml] -------------------------------------------------------------------------------- -bin/kibana-keystore add server.ssl.keystore.password +bin/kibana-keystore add server.ssl.keyPassphrase -------------------------------------------------------------------------------- - -TIP: If your PKCS#12 file isn't protected with a password, depending on how it was generated, you may need to set -`server.ssl.keystore.password` to an empty string. -- + @@ -103,7 +103,7 @@ server.ssl.enabled: true . Restart {kib}. -After making these changes, you must always access {kib} via HTTPS. For example, https://.com. +After making these changes, you must always access {kib} via HTTPS. For example, `https://localhost:5601`. [[configuring-tls-kib-es]] ==== Encrypt traffic between {kib} and {es} @@ -166,8 +166,8 @@ If your PKCS#12 file is encrypted, add the decryption password to your <>. +NOTE: The password for the built-in `elastic` user is typically set as part of the security configuration process on {es}. For more +information, see {ref}/built-in-users.html[Built-in users]. -To manage privileges, open the main menu, then click *Stack Management > Roles*. +. [[kibana-roles]]Create roles and users to grant access to {kib}. ++ +-- +To manage privileges in {kib}, open the main menu, then click *Stack Management > Roles*. The built-in `kibana_admin` role will grant +access to {kib} with administrator privileges. Alternatively, you can create additional roles that grant limited access to {kib}. -If you're using the native realm with Basic Authentication, open then main menu, -then click *Stack Management > Users* to assign roles, or use the -{ref}/security-api.html#security-user-apis[user management APIs]. For example, -the following creates a user named `jacknich` and assigns it the `kibana_admin` -role: +If you're using the default native realm with Basic Authentication, open the main menu, then click *Stack Management > Users* to create +users and assign roles, or use the {es} {ref}/security-api.html#security-user-apis[user management APIs]. For example, the following creates +a user named `jacknich` and assigns it the `kibana_admin` role: [source,js] -------------------------------------------------------------------------------- @@ -98,6 +98,8 @@ POST /_security/user/jacknich } -------------------------------------------------------------------------------- // CONSOLE + +TIP: For more information on Basic Authentication and additional methods of authenticating {kib} users, see <>. -- . Grant users access to the indices that they will be working with in {kib}. @@ -111,17 +113,11 @@ on specific index patterns. For more information, see -- -. Verify that you can log in as a user. If you are running -{kib} locally, go to `https://localhost:5601` and enter the credentials for a -user you've assigned a {kib} user role. For example, you could log in as the user -`jacknich`. +. Log out of {kib} and verify that you can log in as a normal user. If you are running {kib} locally, go to `https://localhost:5601` and +enter the credentials for a user you've assigned a {kib} user role. For example, you could log in as the user `jacknich`. + --- - -NOTE: This must be a user who has been assigned <>. -{kib} server credentials should only be used internally by the {kib} server. - --- +NOTE: This must be a user who has been assigned <>. {kib} server credentials (the built-in +`kibana_system` user) should only be used internally by the {kib} server. include::authentication/index.asciidoc[] include::securing-communications/index.asciidoc[] From 3fba4763fb332ca1f76ac6f255e3dc00ecf4fe7b Mon Sep 17 00:00:00 2001 From: Constance Date: Tue, 5 Jan 2021 08:36:40 -0800 Subject: [PATCH 32/32] [App Search] Minor var names follow-up (#87258) * Var rename - so it doesn't sound negative or like a bug, but is instead an anticipated load/use case - remove unncessary function - move declaration down to right before it's used * [Proposal] Other misc cleanup - Rename engineNameParam to engineNameFromUrl to make reading flow a little bit more nicely + hopefully make the var source a bit clearer - Change other references back to engineName for simplicity (they should really only be running after engineName has already been set, so there shouldn't be any race conditions there - moving engineBreadcrumb to after Loading should also solve that) --- .../components/engine/engine_router.test.tsx | 3 +-- .../components/engine/engine_router.tsx | 19 +++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx index 74976c1c61f0c..cbaa347d65732 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx @@ -57,8 +57,7 @@ describe('EngineRouter', () => { }); it('redirects to engines list and flashes an error if the engine param was not found', () => { - (useParams as jest.Mock).mockReturnValue({ engineName: '404-engine' }); - setMockValues({ ...values, engineNotFound: true }); + setMockValues({ ...values, engineNotFound: true, engineName: '404-engine' }); const wrapper = shallow(); expect(wrapper.find(Redirect).prop('to')).toEqual('/engines'); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx index d3501a5ee7af3..ce7675cef9bb1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx @@ -69,31 +69,30 @@ export const EngineRouter: React.FC = () => { }, } = useValues(AppLogic); + const { engineName: engineNameFromUrl } = useParams() as { engineName: string }; const { engineName, dataLoading, engineNotFound } = useValues(EngineLogic); const { setEngineName, initializeEngine, clearEngine } = useActions(EngineLogic); - const { engineName: engineNameParam } = useParams() as { engineName: string }; - const engineBreadcrumb = [ENGINES_TITLE, engineNameParam]; - - const isEngineInStateStale = () => engineName !== engineNameParam; - useEffect(() => { - setEngineName(engineNameParam); + setEngineName(engineNameFromUrl); initializeEngine(); return clearEngine; - }, [engineNameParam]); + }, [engineNameFromUrl]); if (engineNotFound) { setQueuedErrorMessage( i18n.translate('xpack.enterpriseSearch.appSearch.engine.notFound', { - defaultMessage: "No engine with name '{engineNameParam}' could be found.", - values: { engineNameParam }, + defaultMessage: "No engine with name '{engineName}' could be found.", + values: { engineName }, }) ); return ; } - if (isEngineInStateStale() || dataLoading) return ; + const isLoadingNewEngine = engineName !== engineNameFromUrl; + if (isLoadingNewEngine || dataLoading) return ; + + const engineBreadcrumb = [ENGINES_TITLE, engineName]; return (