mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
* url drilldowns * onSingleValueTrigger * cleanup * tslint * revert changes to ui_actions_service * remove unused method added to es_tooltip_property * remove unused file * update drilldown docs to reflect maps supports URL drilldowns * add functional test case for URL drilldown * do not show URL drilldowns in geometry filter action selection Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
8a0c7bedf8
commit
d1ece89f01
12 changed files with 163 additions and 51 deletions
|
@ -3,7 +3,7 @@
|
|||
== Create custom dashboard actions
|
||||
|
||||
Custom dashboard actions, also known as drilldowns, allow you to create
|
||||
workflows for analyzing and troubleshooting your data. Drilldowns apply only to the panel that you created the drilldown from, and are not shared across all of the panels. Each panel can have multiple drilldowns.
|
||||
workflows for analyzing and troubleshooting your data. Drilldowns apply only to the panel that you created the drilldown from, and are not shared across all of the panels. Each panel can have multiple drilldowns.
|
||||
|
||||
Third-party developers can create drilldowns. To learn how to code drilldowns, refer to {kib-repo}blob/{branch}/x-pack/examples/ui_actions_enhanced_examples[this example plugin].
|
||||
|
||||
|
@ -28,7 +28,7 @@ Dashboard drilldowns enable you to open a dashboard from another dashboard,
|
|||
taking the time range, filters, and other parameters with you,
|
||||
so the context remains the same. Dashboard drilldowns help you to continue your analysis from a new perspective.
|
||||
|
||||
For example, if you have a dashboard that shows the overall status of multiple data center,
|
||||
For example, if you have a dashboard that shows the overall status of multiple data center,
|
||||
you can create a drilldown that navigates from the overall status dashboard to a dashboard
|
||||
that shows a single data center or server.
|
||||
|
||||
|
@ -41,14 +41,14 @@ Destination URLs can be dynamic, depending on the dashboard context or user inte
|
|||
For example, if you have a dashboard that shows data from a Github repository, you can create a URL drilldown
|
||||
that opens Github from the dashboard.
|
||||
|
||||
Some panels support multiple interactions, also known as triggers.
|
||||
Some panels support multiple interactions, also known as triggers.
|
||||
The <<variables,variables>> you use to create a <<url_templating, URL template>> depends on the trigger you choose. URL drilldowns support these types of triggers:
|
||||
|
||||
* *Single click* — A single data point in the visualization.
|
||||
|
||||
* *Range selection* — A range of values in a visualization.
|
||||
|
||||
For example, *Single click* has `{{event.value}}` and *Range selection* has `{{event.from}}` and `{{event.to}}`.
|
||||
For example, *Single click* has `{{event.value}}` and *Range selection* has `{{event.from}}` and `{{event.to}}`.
|
||||
|
||||
To disable URL drilldowns on your {kib} instance, disable the plugin:
|
||||
|
||||
|
@ -77,20 +77,20 @@ The following panels support dashboard and URL drilldowns.
|
|||
^| X
|
||||
|
||||
| Controls
|
||||
^|
|
||||
^|
|
||||
^|
|
||||
^|
|
||||
|
||||
| Data Table
|
||||
^| X
|
||||
^| X
|
||||
|
||||
| Gauge
|
||||
^|
|
||||
^|
|
||||
^|
|
||||
^|
|
||||
|
||||
| Goal
|
||||
^|
|
||||
^|
|
||||
^|
|
||||
^|
|
||||
|
||||
| Heat map
|
||||
^| X
|
||||
|
@ -106,15 +106,15 @@ The following panels support dashboard and URL drilldowns.
|
|||
|
||||
| Maps
|
||||
^| X
|
||||
^|
|
||||
^| X
|
||||
|
||||
| Markdown
|
||||
^|
|
||||
^|
|
||||
^|
|
||||
^|
|
||||
|
||||
| Metric
|
||||
^|
|
||||
^|
|
||||
^|
|
||||
^|
|
||||
|
||||
| Pie
|
||||
^| X
|
||||
|
@ -122,7 +122,7 @@ The following panels support dashboard and URL drilldowns.
|
|||
|
||||
| TSVB
|
||||
^| X
|
||||
^|
|
||||
^|
|
||||
|
||||
| Tag Cloud
|
||||
^| X
|
||||
|
@ -130,11 +130,11 @@ The following panels support dashboard and URL drilldowns.
|
|||
|
||||
| Timelion
|
||||
^| X
|
||||
^|
|
||||
^|
|
||||
|
||||
| Vega
|
||||
^| X
|
||||
^|
|
||||
^|
|
||||
|
||||
| Vertical Bar
|
||||
^| X
|
||||
|
@ -192,7 +192,7 @@ image::images/drilldown_create.png[Create drilldown with entries for drilldown n
|
|||
|
||||
. Click *Create drilldown*.
|
||||
+
|
||||
The drilldown is stored as dashboard metadata.
|
||||
The drilldown is stored as dashboard metadata.
|
||||
|
||||
. Save the dashboard.
|
||||
+
|
||||
|
@ -226,7 +226,7 @@ image:images/url_drilldown_go_to_github.gif[Drilldown on pie chart that navigate
|
|||
|
||||
.. Select *Go to URL*.
|
||||
|
||||
.. Enter the URL template:
|
||||
.. Enter the URL template:
|
||||
+
|
||||
[source, bash]
|
||||
----
|
||||
|
@ -240,7 +240,7 @@ image:images/url_drilldown_url_template.png[URL template input]
|
|||
|
||||
.. Click *Create drilldown*.
|
||||
+
|
||||
The drilldown is stored as dashboard metadata.
|
||||
The drilldown is stored as dashboard metadata.
|
||||
|
||||
. Save the dashboard.
|
||||
+
|
||||
|
|
|
@ -8,6 +8,7 @@ import React, { Component } from 'react';
|
|||
import { EuiFormRow, EuiSuperSelect, EuiIcon } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public';
|
||||
import { isUrlDrilldown } from '../trigger_actions/trigger_utils';
|
||||
|
||||
interface Props {
|
||||
value?: string;
|
||||
|
@ -41,7 +42,7 @@ export class ActionSelect extends Component<Props, State> {
|
|||
}
|
||||
const actions = await this.props.getFilterActions();
|
||||
if (this._isMounted) {
|
||||
this.setState({ actions });
|
||||
this.setState({ actions: actions.filter((action) => !isUrlDrilldown(action)) });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import { LayerPanel } from '../layer_panel';
|
|||
import { AddLayerPanel } from '../add_layer_panel';
|
||||
import { ExitFullScreenButton } from '../../../../../../src/plugins/kibana_react/public';
|
||||
import { getIndexPatternsFromIds } from '../../index_pattern_util';
|
||||
import { ES_GEO_FIELD_TYPE } from '../../../common/constants';
|
||||
import { ES_GEO_FIELD_TYPE, RawValue } from '../../../common/constants';
|
||||
import { indexPatterns as indexPatternsUtils } from '../../../../../../src/plugins/data/public';
|
||||
import { FLYOUT_STATE } from '../../reducers/ui';
|
||||
import { MapSettingsPanel } from '../map_settings_panel';
|
||||
|
@ -40,6 +40,7 @@ interface Props {
|
|||
backgroundColor: string;
|
||||
getFilterActions?: () => Promise<Action[]>;
|
||||
getActionContext?: () => ActionExecutionContext;
|
||||
onSingleValueTrigger?: (actionId: string, key: string, value: RawValue) => void;
|
||||
areLayersLoaded: boolean;
|
||||
cancelAllInFlightRequests: () => void;
|
||||
exitFullScreen: () => void;
|
||||
|
@ -191,6 +192,7 @@ export class MapContainer extends Component<Props, State> {
|
|||
addFilters,
|
||||
getFilterActions,
|
||||
getActionContext,
|
||||
onSingleValueTrigger,
|
||||
flyoutDisplay,
|
||||
isFullScreen,
|
||||
exitFullScreen,
|
||||
|
@ -250,6 +252,7 @@ export class MapContainer extends Component<Props, State> {
|
|||
addFilters={addFilters}
|
||||
getFilterActions={getFilterActions}
|
||||
getActionContext={getActionContext}
|
||||
onSingleValueTrigger={onSingleValueTrigger}
|
||||
geoFields={this.state.geoFields}
|
||||
renderTooltipContent={renderTooltipContent}
|
||||
/>
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../../../src/plugins/data/public';
|
||||
import { isUrlDrilldown } from '../../../trigger_actions/trigger_utils';
|
||||
|
||||
export class FeatureProperties extends React.Component {
|
||||
state = {
|
||||
|
@ -114,21 +115,37 @@ export class FeatureProperties extends React.Component {
|
|||
_renderFilterActions(tooltipProperty) {
|
||||
const panel = {
|
||||
id: 0,
|
||||
items: this.state.actions.map((action) => {
|
||||
const actionContext = this.props.getActionContext();
|
||||
const iconType = action.getIconType(actionContext);
|
||||
const name = action.getDisplayName(actionContext);
|
||||
return {
|
||||
name,
|
||||
icon: iconType ? <EuiIcon type={iconType} /> : null,
|
||||
onClick: async () => {
|
||||
this.props.onCloseTooltip();
|
||||
const filters = await tooltipProperty.getESFilters();
|
||||
this.props.addFilters(filters, action.id);
|
||||
},
|
||||
['data-test-subj']: `mapFilterActionButton__${name}`,
|
||||
};
|
||||
}),
|
||||
items: this.state.actions
|
||||
.filter((action) => {
|
||||
if (isUrlDrilldown(action)) {
|
||||
return !!this.props.onSingleValueTrigger;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((action) => {
|
||||
const actionContext = this.props.getActionContext();
|
||||
const iconType = action.getIconType(actionContext);
|
||||
const name = action.getDisplayName(actionContext);
|
||||
return {
|
||||
name: name ? name : action.id,
|
||||
icon: iconType ? <EuiIcon type={iconType} /> : null,
|
||||
onClick: async () => {
|
||||
this.props.onCloseTooltip();
|
||||
|
||||
if (isUrlDrilldown(action)) {
|
||||
this.props.onSingleValueTrigger(
|
||||
action.id,
|
||||
tooltipProperty.getPropertyKey(),
|
||||
tooltipProperty.getRawValue()
|
||||
);
|
||||
} else {
|
||||
const filters = await tooltipProperty.getESFilters();
|
||||
this.props.addFilters(filters, action.id);
|
||||
}
|
||||
},
|
||||
['data-test-subj']: `mapFilterActionButton__${name}`,
|
||||
};
|
||||
}),
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -183,6 +183,7 @@ export class FeaturesTooltip extends Component {
|
|||
addFilters={this.props.addFilters}
|
||||
getFilterActions={this.props.getFilterActions}
|
||||
getActionContext={this.props.getActionContext}
|
||||
onSingleValueTrigger={this.props.onSingleValueTrigger}
|
||||
showFilterActions={this._showFilterActionsView}
|
||||
/>
|
||||
{this._renderActions(geoFields)}
|
||||
|
|
|
@ -323,6 +323,7 @@ export class MBMap extends React.Component {
|
|||
addFilters={this.props.addFilters}
|
||||
getFilterActions={this.props.getFilterActions}
|
||||
getActionContext={this.props.getActionContext}
|
||||
onSingleValueTrigger={this.props.onSingleValueTrigger}
|
||||
geoFields={this.props.geoFields}
|
||||
renderTooltipContent={this.props.renderTooltipContent}
|
||||
/>
|
||||
|
|
|
@ -201,6 +201,7 @@ export class TooltipControl extends React.Component {
|
|||
addFilters={this.props.addFilters}
|
||||
getFilterActions={this.props.getFilterActions}
|
||||
getActionContext={this.props.getActionContext}
|
||||
onSingleValueTrigger={this.props.onSingleValueTrigger}
|
||||
renderTooltipContent={this.props.renderTooltipContent}
|
||||
geoFields={this.props.geoFields}
|
||||
features={features}
|
||||
|
|
|
@ -119,6 +119,7 @@ export class TooltipPopover extends Component {
|
|||
addFilters: this.props.addFilters,
|
||||
getFilterActions: this.props.getFilterActions,
|
||||
getActionContext: this.props.getActionContext,
|
||||
onSingleValueTrigger: this.props.onSingleValueTrigger,
|
||||
closeTooltip: this.props.closeTooltip,
|
||||
features: this.props.features,
|
||||
isLocked: this.props.isLocked,
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../src/plugins/data/public';
|
||||
import {
|
||||
APPLY_FILTER_TRIGGER,
|
||||
VALUE_CLICK_TRIGGER,
|
||||
ActionExecutionContext,
|
||||
TriggerContextMapping,
|
||||
} from '../../../../../src/plugins/ui_actions/public';
|
||||
|
@ -57,6 +58,7 @@ import {
|
|||
getExistingMapPath,
|
||||
MAP_SAVED_OBJECT_TYPE,
|
||||
MAP_PATH,
|
||||
RawValue,
|
||||
} from '../../common/constants';
|
||||
import { RenderToolTipContent } from '../classes/tooltips/tooltip_property';
|
||||
import { getUiActions, getCoreI18n, getHttp } from '../kibana_services';
|
||||
|
@ -65,6 +67,7 @@ import { MapContainer } from '../connected_components/map_container';
|
|||
import { SavedMap } from '../routes/map_page';
|
||||
import { getIndexPatternsFromIds } from '../index_pattern_util';
|
||||
import { getMapAttributeService } from '../map_attribute_service';
|
||||
import { isUrlDrilldown, toValueClickDataFormat } from '../trigger_actions/trigger_utils';
|
||||
|
||||
import {
|
||||
MapByValueInput,
|
||||
|
@ -202,7 +205,7 @@ export class MapEmbeddable
|
|||
}
|
||||
|
||||
public supportedTriggers(): Array<keyof TriggerContextMapping> {
|
||||
return [APPLY_FILTER_TRIGGER];
|
||||
return [APPLY_FILTER_TRIGGER, VALUE_CLICK_TRIGGER];
|
||||
}
|
||||
|
||||
setRenderTooltipContent = (renderTooltipContent: RenderToolTipContent) => {
|
||||
|
@ -290,6 +293,7 @@ export class MapEmbeddable
|
|||
<Provider store={this._savedMap.getStore()}>
|
||||
<I18nContext>
|
||||
<MapContainer
|
||||
onSingleValueTrigger={this.onSingleValueTrigger}
|
||||
addFilters={this.input.hideFilterActions ? null : this.addFilters}
|
||||
getFilterActions={this.getFilterActions}
|
||||
getActionContext={this.getActionContext}
|
||||
|
@ -320,6 +324,20 @@ export class MapEmbeddable
|
|||
return await getIndexPatternsFromIds(queryableIndexPatternIds);
|
||||
}
|
||||
|
||||
onSingleValueTrigger = (actionId: string, key: string, value: RawValue) => {
|
||||
const action = getUiActions().getAction(actionId);
|
||||
if (!action) {
|
||||
throw new Error('Unable to apply action, could not locate action');
|
||||
}
|
||||
const executeContext = {
|
||||
...this.getActionContext(),
|
||||
data: {
|
||||
data: toValueClickDataFormat(key, value),
|
||||
},
|
||||
};
|
||||
action.execute(executeContext);
|
||||
};
|
||||
|
||||
addFilters = async (filters: Filter[], actionId: string = ACTION_GLOBAL_APPLY_FILTER) => {
|
||||
const executeContext = {
|
||||
...this.getActionContext(),
|
||||
|
@ -333,10 +351,24 @@ export class MapEmbeddable
|
|||
};
|
||||
|
||||
getFilterActions = async () => {
|
||||
return await getUiActions().getTriggerCompatibleActions(APPLY_FILTER_TRIGGER, {
|
||||
const filterActions = await getUiActions().getTriggerCompatibleActions(APPLY_FILTER_TRIGGER, {
|
||||
embeddable: this,
|
||||
filters: [],
|
||||
});
|
||||
const valueClickActions = await getUiActions().getTriggerCompatibleActions(
|
||||
VALUE_CLICK_TRIGGER,
|
||||
{
|
||||
embeddable: this,
|
||||
data: {
|
||||
// uiActions.getTriggerCompatibleActions validates action with provided context
|
||||
// so if event.key and event.value are used in the URL template but can not be parsed from context
|
||||
// then the action is filtered out.
|
||||
// To prevent filtering out actions, provide dummy context when initially fetching actions.
|
||||
data: toValueClickDataFormat('anyfield', 'anyvalue'),
|
||||
},
|
||||
}
|
||||
);
|
||||
return [...filterActions, ...valueClickActions.filter(isUrlDrilldown)];
|
||||
};
|
||||
|
||||
getActionContext = () => {
|
||||
|
|
45
x-pack/plugins/maps/public/trigger_actions/trigger_utils.ts
Normal file
45
x-pack/plugins/maps/public/trigger_actions/trigger_utils.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 { Action } from 'src/plugins/ui_actions/public';
|
||||
import { RawValue } from '../../common/constants';
|
||||
import { DatatableColumnType } from '../../../../../src/plugins/expressions';
|
||||
|
||||
export function isUrlDrilldown(action: Action) {
|
||||
// @ts-expect-error
|
||||
return action.type === 'URL_DRILLDOWN';
|
||||
}
|
||||
|
||||
// VALUE_CLICK_TRIGGER is coupled with expressions and Datatable type
|
||||
// URL drilldown parses event scope from Datatable
|
||||
// https://github.com/elastic/kibana/blob/7.10/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown_scope.ts#L140
|
||||
// In order to use URL drilldown, maps has to package its data in Datatable compatiable format.
|
||||
export function toValueClickDataFormat(key: string, value: RawValue) {
|
||||
return [
|
||||
{
|
||||
table: {
|
||||
columns: [
|
||||
{
|
||||
id: key,
|
||||
meta: {
|
||||
type: 'unknown' as DatatableColumnType, // type is not used by URL drilldown to parse event but is required by DatatableColumnMeta
|
||||
field: key,
|
||||
},
|
||||
name: key,
|
||||
},
|
||||
],
|
||||
rows: [
|
||||
{
|
||||
[key]: value,
|
||||
},
|
||||
],
|
||||
},
|
||||
column: 0,
|
||||
row: 0,
|
||||
value,
|
||||
},
|
||||
];
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
import expect from '@kbn/expect';
|
||||
|
||||
export default function ({ getPageObjects, getService }) {
|
||||
const PageObjects = getPageObjects(['common', 'dashboard', 'maps']);
|
||||
const PageObjects = getPageObjects(['common', 'dashboard', 'discover', 'maps']);
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const filterBar = getService('filterBar');
|
||||
|
@ -48,16 +48,11 @@ export default function ({ getPageObjects, getService }) {
|
|||
});
|
||||
|
||||
describe('panel actions', () => {
|
||||
before(async () => {
|
||||
beforeEach(async () => {
|
||||
await loadDashboardAndOpenTooltip();
|
||||
});
|
||||
|
||||
it('should display more actions button when tooltip is locked', async () => {
|
||||
const exists = await testSubjects.exists('mapTooltipMoreActionsButton');
|
||||
expect(exists).to.be(true);
|
||||
});
|
||||
|
||||
it('should trigger drilldown action when clicked', async () => {
|
||||
it('should trigger dashboard drilldown action when clicked', async () => {
|
||||
await testSubjects.click('mapTooltipMoreActionsButton');
|
||||
await testSubjects.click('mapFilterActionButton__drilldown1');
|
||||
|
||||
|
@ -69,6 +64,16 @@ export default function ({ getPageObjects, getService }) {
|
|||
const hasJoinFilter = await filterBar.hasFilter('shape_name', 'charlie');
|
||||
expect(hasJoinFilter).to.be(true);
|
||||
});
|
||||
|
||||
it('should trigger url drilldown action when clicked', async () => {
|
||||
await testSubjects.click('mapTooltipMoreActionsButton');
|
||||
await testSubjects.click('mapFilterActionButton__urlDrilldownToDiscover');
|
||||
|
||||
// Assert on discover with filter from action
|
||||
await PageObjects.discover.waitForDiscoverAppOnScreen();
|
||||
const hasFilter = await filterBar.hasFilter('name', 'charlie');
|
||||
expect(hasFilter).to.be(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1113,7 +1113,7 @@
|
|||
"title" : "dash for tooltip filter action test",
|
||||
"hits" : 0,
|
||||
"description" : "Zoomed in so entire screen is covered by filter so click to open tooltip can not miss.",
|
||||
"panelsJSON" : "[{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":26,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":-1.31919,\"lon\":59.53306,\"zoom\":9.67},\"isLayerTOCOpen\":false,\"openTOCDetails\":[\"n1t6f\"],\"hiddenLayers\":[],\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"669a3521-1215-4228-9ced-77e2edf5ad17\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"drilldown1\",\"config\":{\"dashboardId\":\"19906970-2e40-11e9-85cb-6965aae20f13\",\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}}},\"panelRefName\":\"panel_0\"}]",
|
||||
"panelsJSON" : "[{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":26,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":-1.31919,\"lon\":59.53306,\"zoom\":9.67},\"isLayerTOCOpen\":false,\"openTOCDetails\":[\"n1t6f\"],\"hiddenLayers\":[],\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"669a3521-1215-4228-9ced-77e2edf5ad17\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"drilldown1\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}},{\"eventId\":\"b9c20d96-03ce-4dcc-8823-e3503311172e\",\"triggers\":[\"VALUE_CLICK_TRIGGER\"],\"action\":{\"name\":\"urlDrilldownToDiscover\",\"config\":{\"url\":{\"template\":\"{{kibanaUrl}}/app/discover#/?_a=(columns:!(_source),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'561253e0-f731-11e8-8487-11b9dd924f96',key:{{event.key}},negate:!f,params:(query:{{event.value}}),type:phrase),query:(match_phrase:({{event.key}}:{{event.value}})))),index:'561253e0-f731-11e8-8487-11b9dd924f96',interval:auto,query:(language:kuery,query:''),sort:!())\"},\"openInNewTab\":false},\"factoryId\":\"URL_DRILLDOWN\"}}]}}},\"panelRefName\":\"panel_0\"}]",
|
||||
"optionsJSON" : "{\"useMargins\":true,\"hidePanelTitles\":false}",
|
||||
"version" : 1,
|
||||
"timeRestore" : true,
|
||||
|
@ -1129,6 +1129,11 @@
|
|||
},
|
||||
"type" : "dashboard",
|
||||
"references" : [
|
||||
{
|
||||
"name" : "drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:669a3521-1215-4228-9ced-77e2edf5ad17:dashboardId",
|
||||
"type" : "dashboard",
|
||||
"id" : "19906970-2e40-11e9-85cb-6965aae20f13"
|
||||
},
|
||||
{
|
||||
"name" : "panel_0",
|
||||
"type" : "map",
|
||||
|
@ -1136,9 +1141,9 @@
|
|||
}
|
||||
],
|
||||
"migrationVersion" : {
|
||||
"dashboard" : "7.3.0"
|
||||
"dashboard" : "7.11.0"
|
||||
},
|
||||
"updated_at" : "2020-08-26T14:32:27.854Z"
|
||||
"updated_at" : "2020-11-19T15:12:25.703Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue