mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Use "Apply_filter_trigger" in dashboard drilldown (#71468)
* attach dashboard drilldown to apply filter trigger * fix types Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
9b570a9bf1
commit
abfda1f792
18 changed files with 225 additions and 196 deletions
|
@ -52,5 +52,6 @@ esFilters: {
|
|||
convertRangeFilterToTimeRangeString: typeof convertRangeFilterToTimeRangeString;
|
||||
mapAndFlattenFilters: (filters: import("../common").Filter[]) => import("../common").Filter[];
|
||||
extractTimeFilter: typeof extractTimeFilter;
|
||||
extractTimeRange: typeof extractTimeRange;
|
||||
}
|
||||
```
|
||||
|
|
|
@ -32,7 +32,11 @@ export {
|
|||
export { DashboardConstants, createDashboardEditUrl } from './dashboard_constants';
|
||||
|
||||
export { DashboardStart, DashboardUrlGenerator } from './plugin';
|
||||
export { DASHBOARD_APP_URL_GENERATOR, createDashboardUrlGenerator } from './url_generator';
|
||||
export {
|
||||
DASHBOARD_APP_URL_GENERATOR,
|
||||
createDashboardUrlGenerator,
|
||||
DashboardUrlGeneratorState,
|
||||
} from './url_generator';
|
||||
export { addEmbeddableToDashboardUrl } from './url_utils/url_helper';
|
||||
export { SavedObjectDashboard } from './saved_dashboards';
|
||||
export { SavedDashboardPanel } from './types';
|
||||
|
|
|
@ -65,6 +65,7 @@ import {
|
|||
ACTION_REPLACE_PANEL,
|
||||
ClonePanelAction,
|
||||
ClonePanelActionContext,
|
||||
createDashboardContainerByValueRenderer,
|
||||
DASHBOARD_CONTAINER_TYPE,
|
||||
DashboardContainerFactory,
|
||||
DashboardContainerFactoryDefinition,
|
||||
|
@ -77,17 +78,17 @@ import {
|
|||
import {
|
||||
createDashboardUrlGenerator,
|
||||
DASHBOARD_APP_URL_GENERATOR,
|
||||
DashboardAppLinkGeneratorState,
|
||||
DashboardUrlGeneratorState,
|
||||
} from './url_generator';
|
||||
import { createSavedDashboardLoader } from './saved_dashboards';
|
||||
import { DashboardConstants } from './dashboard_constants';
|
||||
import { addEmbeddableToDashboardUrl } from './url_utils/url_helper';
|
||||
import { PlaceholderEmbeddableFactory } from './application/embeddable/placeholder';
|
||||
import { createDashboardContainerByValueRenderer } from './application';
|
||||
import { UrlGeneratorState } from '../../share/public';
|
||||
|
||||
declare module '../../share/public' {
|
||||
export interface UrlGeneratorStateMapping {
|
||||
[DASHBOARD_APP_URL_GENERATOR]: DashboardAppLinkGeneratorState;
|
||||
[DASHBOARD_APP_URL_GENERATOR]: UrlGeneratorState<DashboardUrlGeneratorState>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import {
|
|||
RefreshInterval,
|
||||
} from '../../data/public';
|
||||
import { setStateToKbnUrl } from '../../kibana_utils/public';
|
||||
import { UrlGeneratorsDefinition, UrlGeneratorState } from '../../share/public';
|
||||
import { UrlGeneratorsDefinition } from '../../share/public';
|
||||
import { SavedObjectLoader } from '../../saved_objects/public';
|
||||
import { ViewMode } from '../../embeddable/public';
|
||||
|
||||
|
@ -35,7 +35,7 @@ export const GLOBAL_STATE_STORAGE_KEY = '_g';
|
|||
|
||||
export const DASHBOARD_APP_URL_GENERATOR = 'DASHBOARD_APP_URL_GENERATOR';
|
||||
|
||||
export type DashboardAppLinkGeneratorState = UrlGeneratorState<{
|
||||
export interface DashboardUrlGeneratorState {
|
||||
/**
|
||||
* If given, the dashboard saved object with this id will be loaded. If not given,
|
||||
* a new, unsaved dashboard will be loaded up.
|
||||
|
@ -79,7 +79,7 @@ export type DashboardAppLinkGeneratorState = UrlGeneratorState<{
|
|||
* View mode of the dashboard.
|
||||
*/
|
||||
viewMode?: ViewMode;
|
||||
}>;
|
||||
}
|
||||
|
||||
export const createDashboardUrlGenerator = (
|
||||
getStartServices: () => Promise<{
|
||||
|
|
|
@ -58,6 +58,7 @@ import {
|
|||
changeTimeFilter,
|
||||
mapAndFlattenFilters,
|
||||
extractTimeFilter,
|
||||
extractTimeRange,
|
||||
convertRangeFilterToTimeRangeString,
|
||||
} from './query';
|
||||
|
||||
|
@ -99,6 +100,7 @@ export const esFilters = {
|
|||
convertRangeFilterToTimeRangeString,
|
||||
mapAndFlattenFilters,
|
||||
extractTimeFilter,
|
||||
extractTimeRange,
|
||||
};
|
||||
|
||||
export {
|
||||
|
|
|
@ -499,6 +499,7 @@ export const esFilters: {
|
|||
convertRangeFilterToTimeRangeString: typeof convertRangeFilterToTimeRangeString;
|
||||
mapAndFlattenFilters: (filters: import("../common").Filter[]) => import("../common").Filter[];
|
||||
extractTimeFilter: typeof extractTimeFilter;
|
||||
extractTimeRange: typeof extractTimeRange;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "esKuery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
|
@ -1973,52 +1974,53 @@ export const UI_SETTINGS: {
|
|||
// src/plugins/data/common/es_query/filters/match_all_filter.ts:28:3 - (ae-forgotten-export) The symbol "MatchAllFilterMeta" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/es_query/filters/phrase_filter.ts:33:3 - (ae-forgotten-export) The symbol "PhraseFilterMeta" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/es_query/filters/phrases_filter.ts:31:3 - (ae-forgotten-export) The symbol "PhrasesFilterMeta" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "FilterLabel" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "FILTERS" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "getDisplayValueFromFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "generateFilters" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "changeTimeFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "convertRangeFilterToTimeRangeString" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:65:23 - (ae-forgotten-export) The symbol "extractTimeFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:136:21 - (ae-forgotten-export) The symbol "buildEsQuery" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:136:21 - (ae-forgotten-export) The symbol "getEsQueryConfig" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:136:21 - (ae-forgotten-export) The symbol "luceneStringToDsl" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:136:21 - (ae-forgotten-export) The symbol "decorateQuery" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "FieldFormatsRegistry" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "BoolFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "BytesFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "ColorFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "DurationFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "IpFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "NumberFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "PercentFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "RelativeDateFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "SourceFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "StaticLookupFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "UrlFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "StringFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:176:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:232:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:232:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:232:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:232:27 - (ae-forgotten-export) The symbol "getFromSavedObject" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:232:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:232:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:369:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:369:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:369:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:369:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:371:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:372:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:381:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:382:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:383:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:384:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:388:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:389:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:392:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:393:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:396:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "FilterLabel" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "FILTERS" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "getDisplayValueFromFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "generateFilters" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "changeTimeFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "convertRangeFilterToTimeRangeString" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "extractTimeFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "extractTimeRange" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:138:21 - (ae-forgotten-export) The symbol "buildEsQuery" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:138:21 - (ae-forgotten-export) The symbol "getEsQueryConfig" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:138:21 - (ae-forgotten-export) The symbol "luceneStringToDsl" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:138:21 - (ae-forgotten-export) The symbol "decorateQuery" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "FieldFormatsRegistry" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "BoolFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "BytesFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "ColorFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "DurationFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "IpFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "NumberFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "PercentFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "RelativeDateFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "SourceFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "StaticLookupFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "UrlFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "StringFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "getFromSavedObject" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:371:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:371:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:371:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:371:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:373:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:374:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:383:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:384:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:385:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:386:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:391:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:394:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:395:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/index.ts:398:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:41:60 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/types.ts:54:5 - (ae-forgotten-export) The symbol "createFiltersFromValueClickAction" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/public/types.ts:55:5 - (ae-forgotten-export) The symbol "createFiltersFromRangeSelectAction" needs to be exported by the entry point index.d.ts
|
||||
|
|
|
@ -23,5 +23,5 @@ export * from './types';
|
|||
export { Timefilter, TimefilterContract } from './timefilter';
|
||||
export { TimeHistory, TimeHistoryContract } from './time_history';
|
||||
export { changeTimeFilter, convertRangeFilterToTimeRangeString } from './lib/change_time_filter';
|
||||
export { extractTimeFilter } from './lib/extract_time_filter';
|
||||
export { extractTimeFilter, extractTimeRange } from './lib/extract_time_filter';
|
||||
export { validateTimeRange } from './lib/validate_timerange';
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
*/
|
||||
|
||||
import { keys, partition } from 'lodash';
|
||||
import { Filter, isRangeFilter, RangeFilter } from '../../../../common';
|
||||
import { Filter, isRangeFilter, RangeFilter, TimeRange } from '../../../../common';
|
||||
import { convertRangeFilterToTimeRangeString } from './change_time_filter';
|
||||
|
||||
export function extractTimeFilter(timeFieldName: string, filters: Filter[]) {
|
||||
const [timeRangeFilter, restOfFilters] = partition(filters, (obj: Filter) => {
|
||||
|
@ -36,3 +37,15 @@ export function extractTimeFilter(timeFieldName: string, filters: Filter[]) {
|
|||
timeRangeFilter: timeRangeFilter[0] as RangeFilter | undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function extractTimeRange(
|
||||
filters: Filter[],
|
||||
timeFieldName?: string
|
||||
): { restOfFilters: Filter[]; timeRange?: TimeRange } {
|
||||
if (!timeFieldName) return { restOfFilters: filters, timeRange: undefined };
|
||||
const { timeRangeFilter, restOfFilters } = extractTimeFilter(timeFieldName, filters);
|
||||
return {
|
||||
restOfFilters,
|
||||
timeRange: timeRangeFilter ? convertRangeFilterToTimeRangeString(timeRangeFilter) : undefined,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"requiredBundles": [
|
||||
"kibanaUtils",
|
||||
"embeddableEnhanced",
|
||||
"kibanaReact"
|
||||
"kibanaReact",
|
||||
"uiActions"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -6,7 +6,12 @@
|
|||
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ActionByType } from '../../../../../../../../src/plugins/ui_actions/public';
|
||||
import {
|
||||
ActionByType,
|
||||
APPLY_FILTER_TRIGGER,
|
||||
SELECT_RANGE_TRIGGER,
|
||||
VALUE_CLICK_TRIGGER,
|
||||
} from '../../../../../../../../src/plugins/ui_actions/public';
|
||||
import { toMountPoint } from '../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { isEnhancedEmbeddable } from '../../../../../../embeddable_enhanced/public';
|
||||
import { EmbeddableContext } from '../../../../../../../../src/plugins/embeddable/public';
|
||||
|
@ -42,7 +47,9 @@ export class FlyoutCreateDrilldownAction implements ActionByType<typeof OPEN_FLY
|
|||
if (!supportedTriggers || !supportedTriggers.length) return false;
|
||||
if (context.embeddable.getRoot().type !== 'dashboard') return false;
|
||||
|
||||
return supportedTriggers.indexOf('VALUE_CLICK_TRIGGER') > -1;
|
||||
return supportedTriggers.some((trigger) =>
|
||||
[VALUE_CLICK_TRIGGER, SELECT_RANGE_TRIGGER, APPLY_FILTER_TRIGGER].includes(trigger)
|
||||
);
|
||||
}
|
||||
|
||||
public async isCompatible(context: EmbeddableContext) {
|
||||
|
|
|
@ -4,4 +4,11 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* note:
|
||||
* don't change this string without carefull consideration,
|
||||
* because it is stored in saved objects.
|
||||
* Also temporary dashboard drilldown migration code inside embeddable plugin relies on it
|
||||
* x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts
|
||||
*/
|
||||
export const DASHBOARD_TO_DASHBOARD_DRILLDOWN = 'DASHBOARD_TO_DASHBOARD_DRILLDOWN';
|
||||
|
|
|
@ -5,9 +5,8 @@
|
|||
*/
|
||||
|
||||
import { DashboardToDashboardDrilldown } from './drilldown';
|
||||
import { savedObjectsServiceMock, coreMock } from '../../../../../../../src/core/public/mocks';
|
||||
import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks';
|
||||
import { ActionContext, Config } from './types';
|
||||
import { Config } from './types';
|
||||
import { coreMock, savedObjectsServiceMock } from '../../../../../../../src/core/public/mocks';
|
||||
import {
|
||||
Filter,
|
||||
FilterStateStore,
|
||||
|
@ -15,16 +14,13 @@ import {
|
|||
RangeFilter,
|
||||
TimeRange,
|
||||
} from '../../../../../../../src/plugins/data/common';
|
||||
import { esFilters } from '../../../../../../../src/plugins/data/public';
|
||||
|
||||
import {
|
||||
ApplyGlobalFilterActionContext,
|
||||
esFilters,
|
||||
} from '../../../../../../../src/plugins/data/public';
|
||||
// convenient to use real implementation here.
|
||||
import { createDashboardUrlGenerator } from '../../../../../../../src/plugins/dashboard/public/url_generator';
|
||||
import { UrlGeneratorsService } from '../../../../../../../src/plugins/share/public/url_generators';
|
||||
import { VisualizeEmbeddableContract } from '../../../../../../../src/plugins/visualizations/public';
|
||||
import {
|
||||
RangeSelectContext,
|
||||
ValueClickContext,
|
||||
} from '../../../../../../../src/plugins/embeddable/public';
|
||||
import { StartDependencies } from '../../../plugin';
|
||||
import { SavedObjectLoader } from '../../../../../../../src/plugins/saved_objects/public';
|
||||
import { StartServicesGetter } from '../../../../../../../src/plugins/kibana_utils/public/core';
|
||||
|
@ -82,11 +78,10 @@ describe('.execute() & getHref', () => {
|
|||
config: Partial<Config>,
|
||||
embeddableInput: { filters?: Filter[]; timeRange?: TimeRange; query?: Query },
|
||||
filtersFromEvent: Filter[],
|
||||
useRangeEvent = false
|
||||
timeFieldName?: string
|
||||
) {
|
||||
const navigateToApp = jest.fn();
|
||||
const getUrlForApp = jest.fn((app, opt) => `${app}/${opt.path}`);
|
||||
const dataPluginActions = dataPluginMock.createStartContract().actions;
|
||||
const savedObjectsClient = savedObjectsServiceMock.createStartContract().client;
|
||||
|
||||
const drilldown = new DashboardToDashboardDrilldown({
|
||||
|
@ -102,9 +97,6 @@ describe('.execute() & getHref', () => {
|
|||
},
|
||||
plugins: {
|
||||
uiActionsEnhanced: {},
|
||||
data: {
|
||||
actions: dataPluginActions,
|
||||
},
|
||||
},
|
||||
self: {},
|
||||
})) as unknown) as StartServicesGetter<Pick<StartDependencies, 'data' | 'uiActionsEnhanced'>>,
|
||||
|
@ -119,12 +111,6 @@ describe('.execute() & getHref', () => {
|
|||
)
|
||||
),
|
||||
});
|
||||
const selectRangeFiltersSpy = jest
|
||||
.spyOn(dataPluginActions, 'createFiltersFromRangeSelectAction')
|
||||
.mockImplementation(() => Promise.resolve(filtersFromEvent));
|
||||
const valueClickFiltersSpy = jest
|
||||
.spyOn(dataPluginActions, 'createFiltersFromValueClickAction')
|
||||
.mockImplementation(() => Promise.resolve(filtersFromEvent));
|
||||
|
||||
const completeConfig: Config = {
|
||||
dashboardId: 'id',
|
||||
|
@ -134,12 +120,7 @@ describe('.execute() & getHref', () => {
|
|||
};
|
||||
|
||||
const context = ({
|
||||
data: {
|
||||
...(useRangeEvent
|
||||
? ({ range: {} } as RangeSelectContext['data'])
|
||||
: ({ data: [] } as ValueClickContext['data'])),
|
||||
timeFieldName: 'order_date',
|
||||
},
|
||||
filters: filtersFromEvent,
|
||||
embeddable: {
|
||||
getInput: () => ({
|
||||
filters: [],
|
||||
|
@ -148,18 +129,11 @@ describe('.execute() & getHref', () => {
|
|||
...embeddableInput,
|
||||
}),
|
||||
},
|
||||
} as unknown) as ActionContext<VisualizeEmbeddableContract>;
|
||||
timeFieldName,
|
||||
} as unknown) as ApplyGlobalFilterActionContext;
|
||||
|
||||
await drilldown.execute(completeConfig, context);
|
||||
|
||||
if (useRangeEvent) {
|
||||
expect(selectRangeFiltersSpy).toBeCalledTimes(1);
|
||||
expect(valueClickFiltersSpy).toBeCalledTimes(0);
|
||||
} else {
|
||||
expect(selectRangeFiltersSpy).toBeCalledTimes(0);
|
||||
expect(valueClickFiltersSpy).toBeCalledTimes(1);
|
||||
}
|
||||
|
||||
expect(navigateToApp).toBeCalledTimes(1);
|
||||
expect(navigateToApp.mock.calls[0][0]).toBe('dashboards');
|
||||
|
||||
|
@ -180,8 +154,7 @@ describe('.execute() & getHref', () => {
|
|||
dashboardId: testDashboardId,
|
||||
},
|
||||
{},
|
||||
[],
|
||||
false
|
||||
[]
|
||||
);
|
||||
|
||||
expect(href).toEqual(expect.stringContaining(`view/${testDashboardId}`));
|
||||
|
@ -289,8 +262,7 @@ describe('.execute() & getHref', () => {
|
|||
to: 'now',
|
||||
},
|
||||
},
|
||||
[],
|
||||
false
|
||||
[]
|
||||
);
|
||||
|
||||
expect(href).not.toEqual(expect.stringContaining('now-300m'));
|
||||
|
@ -308,7 +280,7 @@ describe('.execute() & getHref', () => {
|
|||
},
|
||||
},
|
||||
[getMockTimeRangeFilter()],
|
||||
true
|
||||
getMockTimeRangeFilter().meta.key
|
||||
);
|
||||
|
||||
expect(href).not.toEqual(expect.stringContaining('now-300m'));
|
||||
|
|
|
@ -6,20 +6,24 @@
|
|||
|
||||
import React from 'react';
|
||||
import { reactToUiComponent } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
import { DashboardUrlGenerator } from '../../../../../../../src/plugins/dashboard/public';
|
||||
import { ActionContext, Config } from './types';
|
||||
import {
|
||||
DashboardUrlGenerator,
|
||||
DashboardUrlGeneratorState,
|
||||
} from '../../../../../../../src/plugins/dashboard/public';
|
||||
import { CollectConfigContainer } from './components';
|
||||
import { DASHBOARD_TO_DASHBOARD_DRILLDOWN } from './constants';
|
||||
import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../../ui_actions_enhanced/public';
|
||||
import { txtGoToDashboard } from './i18n';
|
||||
import { esFilters } from '../../../../../../../src/plugins/data/public';
|
||||
import { VisualizeEmbeddableContract } from '../../../../../../../src/plugins/visualizations/public';
|
||||
import {
|
||||
isRangeSelectTriggerContext,
|
||||
isValueClickTriggerContext,
|
||||
} from '../../../../../../../src/plugins/embeddable/public';
|
||||
ApplyGlobalFilterActionContext,
|
||||
esFilters,
|
||||
isFilters,
|
||||
isQuery,
|
||||
isTimeRange,
|
||||
} from '../../../../../../../src/plugins/data/public';
|
||||
import { StartServicesGetter } from '../../../../../../../src/plugins/kibana_utils/public';
|
||||
import { StartDependencies } from '../../../plugin';
|
||||
import { Config } from './types';
|
||||
|
||||
export interface Params {
|
||||
start: StartServicesGetter<Pick<StartDependencies, 'data' | 'uiActionsEnhanced'>>;
|
||||
|
@ -27,7 +31,7 @@ export interface Params {
|
|||
}
|
||||
|
||||
export class DashboardToDashboardDrilldown
|
||||
implements Drilldown<Config, ActionContext<VisualizeEmbeddableContract>> {
|
||||
implements Drilldown<Config, ApplyGlobalFilterActionContext> {
|
||||
constructor(protected readonly params: Params) {}
|
||||
|
||||
public readonly id = DASHBOARD_TO_DASHBOARD_DRILLDOWN;
|
||||
|
@ -57,15 +61,12 @@ export class DashboardToDashboardDrilldown
|
|||
|
||||
public readonly getHref = async (
|
||||
config: Config,
|
||||
context: ActionContext<VisualizeEmbeddableContract>
|
||||
context: ApplyGlobalFilterActionContext
|
||||
): Promise<string> => {
|
||||
return this.getDestinationUrl(config, context);
|
||||
};
|
||||
|
||||
public readonly execute = async (
|
||||
config: Config,
|
||||
context: ActionContext<VisualizeEmbeddableContract>
|
||||
) => {
|
||||
public readonly execute = async (config: Config, context: ApplyGlobalFilterActionContext) => {
|
||||
const dashboardPath = await this.getDestinationUrl(config, context);
|
||||
const dashboardHash = dashboardPath.split('#')[1];
|
||||
|
||||
|
@ -76,73 +77,43 @@ export class DashboardToDashboardDrilldown
|
|||
|
||||
private getDestinationUrl = async (
|
||||
config: Config,
|
||||
context: ActionContext<VisualizeEmbeddableContract>
|
||||
context: ApplyGlobalFilterActionContext
|
||||
): Promise<string> => {
|
||||
const {
|
||||
createFiltersFromRangeSelectAction,
|
||||
createFiltersFromValueClickAction,
|
||||
} = this.params.start().plugins.data.actions;
|
||||
const {
|
||||
timeRange: currentTimeRange,
|
||||
query,
|
||||
filters: currentFilters,
|
||||
} = context.embeddable!.getInput();
|
||||
const state: DashboardUrlGeneratorState = {
|
||||
dashboardId: config.dashboardId,
|
||||
};
|
||||
|
||||
// if useCurrentDashboardFilters enabled, then preserve all the filters (pinned and unpinned)
|
||||
// otherwise preserve only pinned
|
||||
const existingFilters =
|
||||
(config.useCurrentFilters
|
||||
? currentFilters
|
||||
: currentFilters?.filter((f) => esFilters.isFilterPinned(f))) ?? [];
|
||||
if (context.embeddable) {
|
||||
const input = context.embeddable.getInput();
|
||||
if (isQuery(input.query) && config.useCurrentFilters) state.query = input.query;
|
||||
|
||||
// if useCurrentDashboardDataRange is enabled, then preserve current time range
|
||||
// if undefined is passed, then destination dashboard will figure out time range itself
|
||||
// for brush event this time range would be overwritten
|
||||
let timeRange = config.useCurrentDateRange ? currentTimeRange : undefined;
|
||||
let filtersFromEvent = await (async () => {
|
||||
try {
|
||||
if (isRangeSelectTriggerContext(context))
|
||||
return await createFiltersFromRangeSelectAction(context.data);
|
||||
if (isValueClickTriggerContext(context))
|
||||
return await createFiltersFromValueClickAction(context.data);
|
||||
// if useCurrentDashboardDataRange is enabled, then preserve current time range
|
||||
// if undefined is passed, then destination dashboard will figure out time range itself
|
||||
// for brush event this time range would be overwritten
|
||||
if (isTimeRange(input.timeRange) && config.useCurrentDateRange)
|
||||
state.timeRange = input.timeRange;
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
`
|
||||
DashboardToDashboard drilldown: can't extract filters from action.
|
||||
Is it not supported action?`,
|
||||
context
|
||||
);
|
||||
|
||||
return [];
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
`
|
||||
DashboardToDashboard drilldown: error extracting filters from action.
|
||||
Continuing without applying filters from event`,
|
||||
e
|
||||
);
|
||||
return [];
|
||||
}
|
||||
})();
|
||||
|
||||
if (context.data.timeFieldName) {
|
||||
const { timeRangeFilter, restOfFilters } = esFilters.extractTimeFilter(
|
||||
context.data.timeFieldName,
|
||||
filtersFromEvent
|
||||
);
|
||||
filtersFromEvent = restOfFilters;
|
||||
if (timeRangeFilter) {
|
||||
timeRange = esFilters.convertRangeFilterToTimeRangeString(timeRangeFilter);
|
||||
}
|
||||
// if useCurrentDashboardFilters enabled, then preserve all the filters (pinned and unpinned)
|
||||
// otherwise preserve only pinned
|
||||
if (isFilters(input.filters))
|
||||
state.filters = config.useCurrentFilters
|
||||
? input.filters
|
||||
: input.filters?.filter((f) => esFilters.isFilterPinned(f));
|
||||
}
|
||||
|
||||
return this.params.getDashboardUrlGenerator().createUrl({
|
||||
dashboardId: config.dashboardId,
|
||||
query: config.useCurrentFilters ? query : undefined,
|
||||
timeRange,
|
||||
filters: [...existingFilters, ...filtersFromEvent],
|
||||
});
|
||||
const {
|
||||
restOfFilters: filtersFromEvent,
|
||||
timeRange: timeRangeFromEvent,
|
||||
} = esFilters.extractTimeRange(context.filters, context.timeFieldName);
|
||||
|
||||
if (filtersFromEvent) {
|
||||
state.filters = [...(state.filters ?? []), ...filtersFromEvent];
|
||||
}
|
||||
|
||||
if (timeRangeFromEvent) {
|
||||
state.timeRange = timeRangeFromEvent;
|
||||
}
|
||||
|
||||
return this.params.getDashboardUrlGenerator().createUrl(state);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,4 @@ export {
|
|||
DashboardToDashboardDrilldown,
|
||||
Params as DashboardToDashboardDrilldownParams,
|
||||
} from './drilldown';
|
||||
export {
|
||||
ActionContext as DashboardToDashboardActionContext,
|
||||
Config as DashboardToDashboardConfig,
|
||||
} from './types';
|
||||
export { Config } from './types';
|
||||
|
|
|
@ -4,16 +4,6 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ValueClickContext,
|
||||
RangeSelectContext,
|
||||
IEmbeddable,
|
||||
} from '../../../../../../../src/plugins/embeddable/public';
|
||||
|
||||
export type ActionContext<T extends IEmbeddable = IEmbeddable> =
|
||||
| ValueClickContext<T>
|
||||
| RangeSelectContext<T>;
|
||||
|
||||
export interface Config {
|
||||
dashboardId?: string;
|
||||
useCurrentFilters: boolean;
|
||||
|
|
|
@ -11,6 +11,9 @@ import {
|
|||
} from './embeddable_action_storage';
|
||||
import { UiActionsEnhancedSerializedEvent } from '../../../ui_actions_enhanced/public';
|
||||
import { of } from '../../../../../src/plugins/kibana_utils/public';
|
||||
// use real const to make test fail in case someone accidentally changes it
|
||||
import { DASHBOARD_TO_DASHBOARD_DRILLDOWN } from '../../../dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown';
|
||||
import { APPLY_FILTER_TRIGGER } from '../../../../../src/plugins/ui_actions/public';
|
||||
|
||||
class TestEmbeddable extends Embeddable<EmbeddableWithDynamicActionsInput> {
|
||||
public readonly type = 'test';
|
||||
|
@ -539,4 +542,42 @@ describe('EmbeddableActionStorage', () => {
|
|||
expect(await storage.list()).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('migrate', () => {
|
||||
test('DASHBOARD_TO_DASHBOARD_DRILLDOWN triggers migration', async () => {
|
||||
const embeddable = new TestEmbeddable();
|
||||
const OTHER_TRIGGER = 'OTHER_TRIGGER';
|
||||
embeddable.updateInput({
|
||||
enhancements: {
|
||||
dynamicActions: {
|
||||
events: [
|
||||
{
|
||||
eventId: '1',
|
||||
triggers: [OTHER_TRIGGER],
|
||||
action: {
|
||||
factoryId: DASHBOARD_TO_DASHBOARD_DRILLDOWN,
|
||||
name: '',
|
||||
config: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
eventId: '2',
|
||||
triggers: [OTHER_TRIGGER],
|
||||
action: {
|
||||
factoryId: 'SOME_OTHER',
|
||||
name: '',
|
||||
config: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
const storage = new EmbeddableActionStorage(embeddable);
|
||||
|
||||
const [event1, event2] = await storage.list();
|
||||
expect(event1.triggers).toEqual([APPLY_FILTER_TRIGGER]);
|
||||
expect(event2.triggers).toEqual([OTHER_TRIGGER]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -46,7 +46,7 @@ export class EmbeddableActionStorage extends AbstractActionStorage {
|
|||
|
||||
public async create(event: SerializedEvent) {
|
||||
const input = this.embbeddable.getInput();
|
||||
const events = input.enhancements?.dynamicActions?.events || [];
|
||||
const events = this.getEventsFromEmbeddable();
|
||||
const exists = !!events.find(({ eventId }) => eventId === event.eventId);
|
||||
|
||||
if (exists) {
|
||||
|
@ -61,7 +61,7 @@ export class EmbeddableActionStorage extends AbstractActionStorage {
|
|||
|
||||
public async update(event: SerializedEvent) {
|
||||
const input = this.embbeddable.getInput();
|
||||
const events = input.enhancements?.dynamicActions?.events || [];
|
||||
const events = this.getEventsFromEmbeddable();
|
||||
const index = events.findIndex(({ eventId }) => eventId === event.eventId);
|
||||
|
||||
if (index === -1) {
|
||||
|
@ -77,7 +77,7 @@ export class EmbeddableActionStorage extends AbstractActionStorage {
|
|||
|
||||
public async remove(eventId: string) {
|
||||
const input = this.embbeddable.getInput();
|
||||
const events = input.enhancements?.dynamicActions?.events || [];
|
||||
const events = this.getEventsFromEmbeddable();
|
||||
const index = events.findIndex((event) => eventId === event.eventId);
|
||||
|
||||
if (index === -1) {
|
||||
|
@ -93,7 +93,7 @@ export class EmbeddableActionStorage extends AbstractActionStorage {
|
|||
|
||||
public async read(eventId: string): Promise<SerializedEvent> {
|
||||
const input = this.embbeddable.getInput();
|
||||
const events = input.enhancements?.dynamicActions?.events || [];
|
||||
const events = this.getEventsFromEmbeddable();
|
||||
const event = events.find((ev) => eventId === ev.eventId);
|
||||
|
||||
if (!event) {
|
||||
|
@ -107,8 +107,28 @@ export class EmbeddableActionStorage extends AbstractActionStorage {
|
|||
}
|
||||
|
||||
public async list(): Promise<SerializedEvent[]> {
|
||||
return this.getEventsFromEmbeddable();
|
||||
}
|
||||
|
||||
private getEventsFromEmbeddable() {
|
||||
const input = this.embbeddable.getInput();
|
||||
const events = input.enhancements?.dynamicActions?.events || [];
|
||||
return events;
|
||||
return this.migrate(events);
|
||||
}
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/71431
|
||||
// Migration implementation should use registry
|
||||
// Action factories implementations should register own migrations
|
||||
private migrate(events: SerializedEvent[]): SerializedEvent[] {
|
||||
return events.map((event) => {
|
||||
// Initially dashboard drilldown relied on VALUE_CLICK & RANGE_SELECT
|
||||
if (event.action.factoryId === 'DASHBOARD_TO_DASHBOARD_DRILLDOWN') {
|
||||
return {
|
||||
...event,
|
||||
triggers: ['FILTER_TRIGGER'],
|
||||
};
|
||||
}
|
||||
return event;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,8 @@ import { DrilldownWizardConfig, FlyoutDrilldownWizard } from '../flyout_drilldow
|
|||
import { FlyoutListManageDrilldowns } from '../flyout_list_manage_drilldowns';
|
||||
import { IStorageWrapper } from '../../../../../../../src/plugins/kibana_utils/public';
|
||||
import {
|
||||
VALUE_CLICK_TRIGGER,
|
||||
SELECT_RANGE_TRIGGER,
|
||||
TriggerContextMapping,
|
||||
APPLY_FILTER_TRIGGER,
|
||||
} from '../../../../../../../src/plugins/ui_actions/public';
|
||||
import { useContainerState } from '../../../../../../../src/plugins/kibana_utils/public';
|
||||
import { DrilldownListItem } from '../list_manage_drilldowns';
|
||||
|
@ -67,8 +66,9 @@ export function createFlyoutManageDrilldowns({
|
|||
return (props: ConnectedFlyoutManageDrilldownsProps) => {
|
||||
const isCreateOnly = props.viewMode === 'create';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/59569
|
||||
const selectedTriggers: Array<keyof TriggerContextMapping> = React.useMemo(
|
||||
() => [VALUE_CLICK_TRIGGER, SELECT_RANGE_TRIGGER],
|
||||
() => [APPLY_FILTER_TRIGGER],
|
||||
[]
|
||||
);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue