[Dashboard] Keep managed panels out of unmanaged dashboards (#176006)

## Summary

Close https://github.com/elastic/kibana/issues/172383
Close https://github.com/elastic/kibana/issues/172384

This PR introduces a [new embeddable-related
registry](https://github.com/elastic/kibana/pull/176006/files#diff-1401b355377c76ab6458756aa0e3177beef5ec56796c58b7a52b5e003f85b5cf)
which clients can use to define a custom transformation from saved
object to embeddable input during the add-panel-from-library sequence.

Then, each content type uses this to communicate whether a particular
object should be added by-ref or by-val based on the presence of
`managed: true` on the saved object
([example](https://github.com/elastic/kibana/pull/176006/files#diff-3baaeaeef5893a5a4db6379a1ed888406a8584cb9d0c7440f273040e4aa28166R157-R167)).



### Managed panels are added by-value to dashboards

<img width="400" alt="Screenshot 2024-02-01 at 12 24 06 PM"
src="42a695d4-fccf-45bf-bd6a-8d8fc606d04e">

### Cloning a managed dashboard inlines all by-ref panels


ca6e763c-cc02-46cb-9164-abd91deca081

### Checklist

Delete any items that are not applicable to this PR.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials — will
happen in https://github.com/elastic/kibana/issues/175150
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed —
https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/5031
- [x] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Drew Tate 2024-02-07 06:46:41 -07:00 committed by GitHub
parent 2101b3f7c4
commit f136782fd4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 413 additions and 103 deletions

View file

@ -14,7 +14,9 @@ import { showSaveModal } from '@kbn/saved-objects-plugin/public';
import { cloneDeep } from 'lodash';
import React from 'react';
import { batch } from 'react-redux';
import { DashboardContainerInput } from '../../../../common';
import { EmbeddableInput, isReferenceOrValueEmbeddable } from '@kbn/embeddable-plugin/public';
import { DashboardContainerInput, DashboardPanelMap } from '../../../../common';
import { DASHBOARD_CONTENT_ID, SAVED_OBJECT_POST_TIME } from '../../../dashboard_constants';
import {
SaveDashboardReturn,
@ -241,12 +243,38 @@ export async function runClone(this: DashboardContainer) {
};
}
const isManaged = this.getState().componentState.managed;
const newPanels = await (async () => {
if (!isManaged) return currentState.panels;
// this is a managed dashboard - unlink all by reference embeddables on clone
const unlinkedPanels: DashboardPanelMap = {};
for (const [panelId, panel] of Object.entries(currentState.panels)) {
const child = this.getChild(panelId);
if (
child &&
isReferenceOrValueEmbeddable(child) &&
child.inputIsRefType(child.getInput() as EmbeddableInput)
) {
const valueTypeInput = await child.getInputAsValueType();
unlinkedPanels[panelId] = {
...panel,
explicitInput: valueTypeInput,
};
continue;
}
unlinkedPanels[panelId] = panel;
}
return unlinkedPanels;
})();
const saveResult = await saveDashboardState({
saveOptions: {
saveAsCopy: true,
},
currentState: {
...stateToSave,
panels: newPanels,
title: newTitle,
},
});

View file

@ -68,7 +68,7 @@ describe('add panel flyout', () => {
getEmbeddableFactory: embeddableStart.getEmbeddableFactory,
}
);
container.addNewEmbeddable = jest.fn();
container.addNewEmbeddable = jest.fn().mockResolvedValue({ id: 'foo' });
});
test('add panel flyout renders SavedObjectFinder', async () => {

View file

@ -32,6 +32,7 @@ import {
SavedObjectEmbeddableInput,
EmbeddableFactoryNotFoundError,
} from '../lib';
import { savedObjectToPanel } from '../registry/saved_object_to_panel_methods';
type FactoryMap = { [key: string]: EmbeddableFactory };
@ -101,12 +102,30 @@ export const AddPanelFlyout = ({
throw new EmbeddableFactoryNotFoundError(type);
}
const embeddable = await container.addNewEmbeddable<SavedObjectEmbeddableInput>(
let embeddableId: string;
if (savedObjectToPanel[type]) {
// this panel type has a custom method for converting saved objects to panels
const panel = savedObjectToPanel[type](savedObject);
const { id: _embeddableId } = await container.addNewEmbeddable(
factoryForSavedObjectType.type,
panel,
savedObject.attributes
);
embeddableId = _embeddableId;
} else {
const { id: _embeddableId } = await container.addNewEmbeddable<SavedObjectEmbeddableInput>(
factoryForSavedObjectType.type,
{ savedObjectId: id },
savedObject.attributes
);
onAddPanel?.(embeddable.id);
embeddableId = _embeddableId;
}
onAddPanel?.(embeddableId);
showSuccessToast(name);
runAddTelemetry(container.type, factoryForSavedObjectType, savedObject);
@ -136,6 +155,14 @@ export const AddPanelFlyout = ({
noItemsMessage={i18n.translate('embeddableApi.addPanel.noMatchingObjectsMessage', {
defaultMessage: 'No matching objects found.',
})}
getTooltipText={(item) => {
return item.managed
? i18n.translate('embeddableApi.addPanel.managedPanelTooltip', {
defaultMessage:
'This panel is managed by Elastic. It can be added but will be unlinked from the library.',
})
: undefined;
}}
/>
</EuiFlyoutBody>
</>

View file

@ -113,6 +113,8 @@ export {
serializeReactEmbeddableTitles,
} from './react_embeddable_system';
export { registerSavedObjectToPanelMethod } from './registry/saved_object_to_panel_methods';
export function plugin(initializerContext: PluginInitializerContext) {
return new EmbeddablePublicPlugin(initializerContext);
}

View file

@ -0,0 +1,22 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
type SavedObjectToPanelMethod<TSavedObjectAttributes, TByValueInput> = (
savedObject: SavedObjectCommon<TSavedObjectAttributes>
) => { savedObjectId: string } | Partial<TByValueInput>;
export const savedObjectToPanel: Record<string, SavedObjectToPanelMethod<any, any>> = {};
export const registerSavedObjectToPanelMethod = <TSavedObjectAttributes, TByValueAttributes>(
savedObjectType: string,
method: SavedObjectToPanelMethod<TSavedObjectAttributes, TByValueAttributes>
) => {
savedObjectToPanel[savedObjectType] = method;
};

View file

@ -9,7 +9,12 @@
const nextTick = () => new Promise((res) => process.nextTick(res));
import lodash from 'lodash';
jest.spyOn(lodash, 'debounce').mockImplementation((fn: any) => fn);
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
jest.spyOn(lodash, 'debounce').mockImplementation((fn: any) => {
fn.cancel = jest.fn();
return fn;
});
import {
EuiInMemoryTable,
EuiLink,
@ -962,4 +967,36 @@ describe('SavedObjectsFinder', () => {
expect(findTestSubject(wrapper, 'tableHeaderCell_references_2')).toHaveLength(0);
});
});
it('should add a tooltip when text is provided', async () => {
(contentClient.mSearch as any as jest.SpyInstance).mockResolvedValue({
hits: [doc, doc2, doc3],
});
const tooltipText = 'This is a tooltip';
render(
<SavedObjectFinder
services={{ uiSettings, contentClient, savedObjectsTagging }}
savedObjectMetaData={metaDataConfig}
getTooltipText={(item) => (item.id === doc3.id ? tooltipText : undefined)}
/>
);
const assertTooltip = async (linkTitle: string, show: boolean) => {
const elem = await screen.findByText(linkTitle);
userEvent.hover(elem);
const tooltip = screen.queryByText(tooltipText);
if (show) {
expect(tooltip).toBeInTheDocument();
} else {
expect(tooltip).toBeNull();
}
};
assertTooltip(doc.attributes.title, false);
assertTooltip(doc2.attributes.title, false);
assertTooltip(doc3.attributes.title, true);
});
});

View file

@ -77,6 +77,7 @@ interface BaseSavedObjectFinder {
leftChildren?: ReactElement | ReactElement[];
children?: ReactElement | ReactElement[];
helpText?: string;
getTooltipText?: (item: SavedObjectFinderItem) => string | undefined;
}
interface SavedObjectFinderFixedPage extends BaseSavedObjectFinder {
@ -288,7 +289,7 @@ export class SavedObjectFinderUi extends React.Component<
? currentSavedObjectMetaData.getTooltipForSavedObject(item.simple)
: `${item.name} (${currentSavedObjectMetaData!.name})`;
return (
const link = (
<EuiLink
onClick={
onChoose
@ -303,6 +304,16 @@ export class SavedObjectFinderUi extends React.Component<
{item.name}
</EuiLink>
);
const tooltipText = this.props.getTooltipText?.(item);
return tooltipText ? (
<EuiToolTip position="left" content={tooltipText}>
{link}
</EuiToolTip>
) : (
link
);
},
},
...(tagColumn ? [tagColumn] : []),

View file

@ -17,13 +17,14 @@ import type {
ContentManagementPublicStart,
} from '@kbn/content-management-plugin/public';
import type { SOWithMetadata } from '@kbn/content-management-utils';
import type { EmbeddableStart } from '@kbn/embeddable-plugin/public';
import { EmbeddableStart, registerSavedObjectToPanelMethod } from '@kbn/embeddable-plugin/public';
import {
getSavedSearch,
saveSavedSearch,
SaveSavedSearchOptions,
getNewSavedSearch,
SavedSearchUnwrapResult,
SearchByValueInput,
} from './services/saved_searches';
import { SavedSearch, SavedSearchAttributes } from '../common/types';
import { SavedSearchType, LATEST_VERSION } from '../common';
@ -35,6 +36,7 @@ import {
getSavedSearchAttributeService,
toSavedSearch,
} from './services/saved_searches';
import { savedObjectToEmbeddableAttributes } from './services/saved_searches/saved_search_attribute_service';
/**
* Saved search plugin public Setup contract
@ -115,6 +117,19 @@ export class SavedSearchPublicPlugin
expressions.registerType(kibanaContext);
registerSavedObjectToPanelMethod<SavedSearchAttributes, SearchByValueInput>(
SavedSearchType,
(savedObject) => {
if (!savedObject.managed) {
return { savedObjectId: savedObject.id };
}
return {
attributes: savedObjectToEmbeddableAttributes(savedObject),
};
}
);
return {};
}

View file

@ -9,6 +9,8 @@
import type { AttributeService, EmbeddableStart } from '@kbn/embeddable-plugin/public';
import type { OnSaveProps } from '@kbn/saved-objects-plugin/public';
import { SEARCH_EMBEDDABLE_TYPE } from '@kbn/discover-utils';
import { SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
import { SavedSearchAttributes } from '../../../common';
import type {
SavedSearch,
SavedSearchByValueAttributes,
@ -41,6 +43,13 @@ export type SavedSearchAttributeService = AttributeService<
SavedSearchUnwrapMetaInfo
>;
export const savedObjectToEmbeddableAttributes = (
savedObject: SavedObjectCommon<SavedSearchAttributes>
) => ({
...savedObject.attributes,
references: savedObject.references,
});
export function getSavedSearchAttributeService(
services: SavedSearchesServiceDeps & {
embeddable: EmbeddableStart;
@ -67,10 +76,7 @@ export function getSavedSearchAttributeService(
const so = await getSearchSavedObject(savedObjectId, createGetSavedSearchDeps(services));
return {
attributes: {
...so.item.attributes,
references: so.item.references,
},
attributes: savedObjectToEmbeddableAttributes(so.item),
metaInfo: {
sharingSavedObjectProps: so.meta,
managed: so.item.managed,

View file

@ -32,6 +32,7 @@
"@kbn/logging",
"@kbn/core-plugins-server",
"@kbn/utility-types",
"@kbn/saved-objects-finder-plugin",
],
"exclude": [
"target/**/*",

View file

@ -47,7 +47,11 @@ import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
import type { ExpressionsSetup, ExpressionsStart } from '@kbn/expressions-plugin/public';
import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public';
import {
EmbeddableSetup,
EmbeddableStart,
registerSavedObjectToPanelMethod,
} from '@kbn/embeddable-plugin/public';
import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public';
import type { NavigationPublicPluginStart as NavigationStart } from '@kbn/navigation-plugin/public';
import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
@ -112,8 +116,14 @@ import {
} from './services';
import { VisualizeConstants } from '../common/constants';
import { EditInLensAction } from './actions/edit_in_lens_action';
import { ListingViewRegistry } from './types';
import { LATEST_VERSION, CONTENT_ID } from '../common/content_management';
import { ListingViewRegistry, SerializedVis } from './types';
import {
LATEST_VERSION,
CONTENT_ID,
VisualizationSavedObjectAttributes,
} from '../common/content_management';
import { SerializedVisData } from '../common';
import { VisualizeByValueInput } from './embeddable/visualize_embeddable';
/**
* Interface for this plugin's returned setup/start contracts.
@ -397,6 +407,37 @@ export class VisualizationsPlugin
name: 'Visualize Library',
});
registerSavedObjectToPanelMethod<VisualizationSavedObjectAttributes, VisualizeByValueInput>(
CONTENT_ID,
(savedObject) => {
const visState = savedObject.attributes.visState;
// not sure if visState actually is ever undefined, but following the type
if (!savedObject.managed || !visState) {
return {
savedObjectId: savedObject.id,
};
}
// data is not always defined, so I added a default value since the extract
// routine in the embeddable factory expects it to be there
const savedVis = JSON.parse(visState) as Omit<SerializedVis, 'data'> & {
data?: SerializedVisData;
};
if (!savedVis.data) {
savedVis.data = {
searchSource: {},
aggs: [],
};
}
return {
savedVis: savedVis as SerializedVis, // now we're sure we have "data" prop
};
}
);
return {
...this.types.setup(),
visEditorsRegistry,

View file

@ -1,17 +1,19 @@
{"attributes":{"allowHidden":false,"fieldAttrs":"{}","fieldFormatMap":"{}","fields":"[]","name":"logstash-*","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"@timestamp","title":"logstash-*"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-18T17:35:58.606Z","id":"5f863f70-4728-4e8d-b441-db08f8c33b28","managed":false,"references":[],"type":"index-pattern","typeMigrationVersion":"8.0.0","updated_at":"2024-01-18T17:35:58.606Z","version":"WzI4LDFd"}
{"attributes":{"description":"","state":{"adHocDataViews":{},"datasourceStates":{"formBased":{"layers":{"e633b1af-3ab4-4bf5-8faa-fefde06c4a4a":{"columnOrder":["f2555a1a-6f93-43fd-bc63-acdfadd47729","d229daf9-9658-4579-99af-01d8adb2f25f"],"columns":{"d229daf9-9658-4579-99af-01d8adb2f25f":{"dataType":"number","isBucketed":false,"label":"Median of bytes","operationType":"median","params":{"emptyAsNull":true},"scale":"ratio","sourceField":"bytes"},"f2555a1a-6f93-43fd-bc63-acdfadd47729":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"dropPartials":false,"includeEmptyRows":true,"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{},"sampling":1}}},"indexpattern":{"layers":{}},"textBased":{"layers":{}}},"filters":[],"internalReferences":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"layers":[{"accessors":["d229daf9-9658-4579-99af-01d8adb2f25f"],"layerId":"e633b1af-3ab4-4bf5-8faa-fefde06c4a4a","layerType":"data","position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"f2555a1a-6f93-43fd-bc63-acdfadd47729"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"Lens vis (managed)","visualizationType":"lnsXY"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-18T17:42:12.920Z","id":"managed-36db-4a3b-a4ba-7a64ab8f130b","managed":true,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"indexpattern-datasource-layer-e633b1af-3ab4-4bf5-8faa-fefde06c4a4a","type":"index-pattern"}],"type":"lens","typeMigrationVersion":"8.9.0","updated_at":"2024-01-18T17:42:12.920Z","version":"WzQ1LDFd"}
{"attributes":{"description":"","state":{"adHocDataViews":{},"datasourceStates":{"formBased":{"layers":{"e633b1af-3ab4-4bf5-8faa-fefde06c4a4a":{"columnOrder":["f2555a1a-6f93-43fd-bc63-acdfadd47729","d229daf9-9658-4579-99af-01d8adb2f25f"],"columns":{"d229daf9-9658-4579-99af-01d8adb2f25f":{"dataType":"number","isBucketed":false,"label":"Median of bytes","operationType":"median","params":{"emptyAsNull":true},"scale":"ratio","sourceField":"bytes"},"f2555a1a-6f93-43fd-bc63-acdfadd47729":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"dropPartials":false,"includeEmptyRows":true,"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{},"sampling":1}}},"indexpattern":{"layers":{}},"textBased":{"layers":{}}},"filters":[],"internalReferences":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"layers":[{"accessors":["d229daf9-9658-4579-99af-01d8adb2f25f"],"layerId":"e633b1af-3ab4-4bf5-8faa-fefde06c4a4a","layerType":"data","position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"f2555a1a-6f93-43fd-bc63-acdfadd47729"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"Managed lens vis","visualizationType":"lnsXY"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-18T17:42:12.920Z","id":"managed-36db-4a3b-a4ba-7a64ab8f130b","managed":true,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"indexpattern-datasource-layer-e633b1af-3ab4-4bf5-8faa-fefde06c4a4a","type":"index-pattern"}],"type":"lens","typeMigrationVersion":"8.9.0","updated_at":"2024-01-18T17:42:12.920Z","version":"WzQ1LDFd"}
{"attributes":{"description":"","state":{"adHocDataViews":{},"datasourceStates":{"formBased":{"layers":{"e633b1af-3ab4-4bf5-8faa-fefde06c4a4a":{"columnOrder":["f2555a1a-6f93-43fd-bc63-acdfadd47729","d229daf9-9658-4579-99af-01d8adb2f25f"],"columns":{"d229daf9-9658-4579-99af-01d8adb2f25f":{"dataType":"number","isBucketed":false,"label":"Median of bytes","operationType":"median","params":{"emptyAsNull":true},"scale":"ratio","sourceField":"bytes"},"f2555a1a-6f93-43fd-bc63-acdfadd47729":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"dropPartials":false,"includeEmptyRows":true,"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{},"sampling":1}}},"indexpattern":{"layers":{}},"textBased":{"layers":{}}},"filters":[],"internalReferences":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"layers":[{"accessors":["d229daf9-9658-4579-99af-01d8adb2f25f"],"layerId":"e633b1af-3ab4-4bf5-8faa-fefde06c4a4a","layerType":"data","position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"f2555a1a-6f93-43fd-bc63-acdfadd47729"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"Lens vis (unmanaged)","visualizationType":"lnsXY"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-18T17:42:12.920Z","id":"unmanaged-36db-4a3b-a4ba-7a64ab8f130b","managed":false,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"indexpattern-datasource-layer-e633b1af-3ab4-4bf5-8faa-fefde06c4a4a","type":"index-pattern"}],"type":"lens","typeMigrationVersion":"8.9.0","updated_at":"2024-01-18T17:42:12.920Z","version":"WzQ1LDFd"}
{"attributes":{"description":"","state":{"adHocDataViews":{},"datasourceStates":{"formBased":{"layers":{"e633b1af-3ab4-4bf5-8faa-fefde06c4a4a":{"columnOrder":["f2555a1a-6f93-43fd-bc63-acdfadd47729","d229daf9-9658-4579-99af-01d8adb2f25f"],"columns":{"d229daf9-9658-4579-99af-01d8adb2f25f":{"dataType":"number","isBucketed":false,"label":"Median of bytes","operationType":"median","params":{"emptyAsNull":true},"scale":"ratio","sourceField":"bytes"},"f2555a1a-6f93-43fd-bc63-acdfadd47729":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"dropPartials":false,"includeEmptyRows":true,"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{},"sampling":1}}},"indexpattern":{"layers":{}},"textBased":{"layers":{}}},"filters":[],"internalReferences":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"layers":[{"accessors":["d229daf9-9658-4579-99af-01d8adb2f25f"],"layerId":"e633b1af-3ab4-4bf5-8faa-fefde06c4a4a","layerType":"data","position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"f2555a1a-6f93-43fd-bc63-acdfadd47729"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"Unmanaged lens vis","visualizationType":"lnsXY"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-18T17:42:12.920Z","id":"unmanaged-36db-4a3b-a4ba-7a64ab8f130b","managed":false,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"indexpattern-datasource-layer-e633b1af-3ab4-4bf5-8faa-fefde06c4a4a","type":"index-pattern"}],"type":"lens","typeMigrationVersion":"8.9.0","updated_at":"2024-01-18T17:42:12.920Z","version":"WzQ1LDFd"}
{"attributes":{"columns":["@tags","clientip"],"description":"","grid":{},"hideChart":false,"isTextBasedQuery":false,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"agent.raw:\\\"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)\\\" \",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"timeRestore":false,"title":"Saved search","usesAdHocDataView":false},"coreMigrationVersion":"8.8.0","created_at":"2024-01-22T18:11:05.016Z","id":"managed-3d62-4113-ac7c-de2e20a68fbc","managed":true,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","typeMigrationVersion":"8.0.0","updated_at":"2024-01-22T18:11:05.016Z","version":"WzIzLDFd"}
{"attributes":{"columns":["@tags","clientip"],"description":"","grid":{},"hideChart":false,"isTextBasedQuery":false,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"agent.raw:\\\"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)\\\" \",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"timeRestore":false,"title":"Managed saved search","usesAdHocDataView":false},"coreMigrationVersion":"8.8.0","created_at":"2024-01-22T18:11:05.016Z","id":"managed-3d62-4113-ac7c-de2e20a68fbc","managed":true,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","typeMigrationVersion":"8.0.0","updated_at":"2024-01-22T18:11:05.016Z","version":"WzIzLDFd"}
{"attributes":{"columns":["@tags","clientip"],"description":"","grid":{},"hideChart":false,"isTextBasedQuery":false,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"agent.raw:\\\"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)\\\" \",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"timeRestore":false,"title":"Saved search","usesAdHocDataView":false},"coreMigrationVersion":"8.8.0","created_at":"2024-01-22T18:11:05.016Z","id":"unmanaged-3d62-4113-ac7c-de2e20a68fbc","managed":false,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","typeMigrationVersion":"8.0.0","updated_at":"2024-01-22T18:11:05.016Z","version":"WzIzLDFd"}
{"attributes":{"columns":["@tags","clientip"],"description":"","grid":{},"hideChart":false,"isTextBasedQuery":false,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"agent.raw:\\\"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)\\\" \",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"timeRestore":false,"title":"Unmanaged saved search","usesAdHocDataView":false},"coreMigrationVersion":"8.8.0","created_at":"2024-01-22T18:11:05.016Z","id":"unmanaged-3d62-4113-ac7c-de2e20a68fbc","managed":false,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","typeMigrationVersion":"8.0.0","updated_at":"2024-01-22T18:11:05.016Z","version":"WzIzLDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"title":"Legacy visualization","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Legacy visualization\",\"type\":\"metrics\",\"aggs\":[],\"params\":{\"id\":\"1a14d0ad-0d74-4470-a189-8f040cddc1a1\",\"type\":\"timeseries\",\"series\":[{\"id\":\"daa8bbf7-86cc-4394-b249-be48da9f7351\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"palette\":{\"type\":\"palette\",\"name\":\"default\"},\"metrics\":[{\"id\":\"795375d9-1aa6-454d-9b23-687e69f3382c\",\"type\":\"count\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"default\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"override_index_pattern\":0,\"series_drop_last_bucket\":0}],\"time_field\":\"\",\"use_kibana_indexes\":true,\"interval\":\"\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"axis_scale\":\"normal\",\"show_legend\":1,\"truncate_legend\":1,\"max_lines_legend\":1,\"show_grid\":1,\"tooltip_mode\":\"show_all\",\"drop_last_bucket\":0,\"index_pattern_ref_name\":\"metrics_0_index_pattern\"}}"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-24T18:53:06.818Z","id":"managed-feb9-4ba6-9538-1b8f67fb4f57","managed":true,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"metrics_0_index_pattern","type":"index-pattern"}],"type":"visualization","typeMigrationVersion":"8.5.0","updated_at":"2024-01-24T18:53:06.818Z","version":"WzEzLDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"title":"Managed legacy visualization","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Legacy visualization\",\"type\":\"metrics\",\"aggs\":[],\"params\":{\"id\":\"1a14d0ad-0d74-4470-a189-8f040cddc1a1\",\"type\":\"timeseries\",\"series\":[{\"id\":\"daa8bbf7-86cc-4394-b249-be48da9f7351\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"palette\":{\"type\":\"palette\",\"name\":\"default\"},\"metrics\":[{\"id\":\"795375d9-1aa6-454d-9b23-687e69f3382c\",\"type\":\"count\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"default\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"override_index_pattern\":0,\"series_drop_last_bucket\":0}],\"time_field\":\"\",\"use_kibana_indexes\":true,\"interval\":\"\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"axis_scale\":\"normal\",\"show_legend\":1,\"truncate_legend\":1,\"max_lines_legend\":1,\"show_grid\":1,\"tooltip_mode\":\"show_all\",\"drop_last_bucket\":0,\"index_pattern_ref_name\":\"metrics_0_index_pattern\"}}"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-24T18:53:06.818Z","id":"managed-feb9-4ba6-9538-1b8f67fb4f57","managed":true,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"metrics_0_index_pattern","type":"index-pattern"}],"type":"visualization","typeMigrationVersion":"8.5.0","updated_at":"2024-01-24T18:53:06.818Z","version":"WzEzLDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"title":"Legacy visualization","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Legacy visualization\",\"type\":\"metrics\",\"aggs\":[],\"params\":{\"id\":\"1a14d0ad-0d74-4470-a189-8f040cddc1a1\",\"type\":\"timeseries\",\"series\":[{\"id\":\"daa8bbf7-86cc-4394-b249-be48da9f7351\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"palette\":{\"type\":\"palette\",\"name\":\"default\"},\"metrics\":[{\"id\":\"795375d9-1aa6-454d-9b23-687e69f3382c\",\"type\":\"count\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"default\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"override_index_pattern\":0,\"series_drop_last_bucket\":0}],\"time_field\":\"\",\"use_kibana_indexes\":true,\"interval\":\"\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"axis_scale\":\"normal\",\"show_legend\":1,\"truncate_legend\":1,\"max_lines_legend\":1,\"show_grid\":1,\"tooltip_mode\":\"show_all\",\"drop_last_bucket\":0,\"index_pattern_ref_name\":\"metrics_0_index_pattern\"}}"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-24T18:53:06.818Z","id":"unmanaged-feb9-4ba6-9538-1b8f67fb4f57","managed":false,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"metrics_0_index_pattern","type":"index-pattern"}],"type":"visualization","typeMigrationVersion":"8.5.0","updated_at":"2024-01-24T18:53:06.818Z","version":"WzEzLDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"title":"Unmanaged legacy visualization","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Legacy visualization\",\"type\":\"metrics\",\"aggs\":[],\"params\":{\"id\":\"1a14d0ad-0d74-4470-a189-8f040cddc1a1\",\"type\":\"timeseries\",\"series\":[{\"id\":\"daa8bbf7-86cc-4394-b249-be48da9f7351\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"palette\":{\"type\":\"palette\",\"name\":\"default\"},\"metrics\":[{\"id\":\"795375d9-1aa6-454d-9b23-687e69f3382c\",\"type\":\"count\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"default\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"override_index_pattern\":0,\"series_drop_last_bucket\":0}],\"time_field\":\"\",\"use_kibana_indexes\":true,\"interval\":\"\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"axis_scale\":\"normal\",\"show_legend\":1,\"truncate_legend\":1,\"max_lines_legend\":1,\"show_grid\":1,\"tooltip_mode\":\"show_all\",\"drop_last_bucket\":0,\"index_pattern_ref_name\":\"metrics_0_index_pattern\"}}"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-24T18:53:06.818Z","id":"unmanaged-feb9-4ba6-9538-1b8f67fb4f57","managed":false,"references":[{"id":"5f863f70-4728-4e8d-b441-db08f8c33b28","name":"metrics_0_index_pattern","type":"index-pattern"}],"type":"visualization","typeMigrationVersion":"8.5.0","updated_at":"2024-01-24T18:53:06.818Z","version":"WzEzLDFd"}
{"attributes":{"description":"","layerListJSON":"[{\"locale\":\"autoselect\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true,\"lightModeDefault\":\"road_map_desaturated\"},\"id\":\"5ff9c98e-e0d3-4aff-ac98-b33c191496b4\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"EMS_VECTOR_TILE\",\"color\":\"\"},\"includeInFitToBounds\":true,\"type\":\"EMS_VECTOR_TILE\"}]","mapStateJSON":"{\"adHocDataViews\":[],\"zoom\":1.4,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":60000},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"customIcons\":[],\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"keydownScrollZoom\":false,\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"showTimesliderToggleButton\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}","title":"Map","uiStateJSON":"{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-24T18:22:40.360Z","id":"managed-d7ab-46eb-a807-8fed28ed8566","managed":true,"references":[],"type":"map","typeMigrationVersion":"8.4.0","updated_at":"2024-01-24T18:23:07.090Z","version":"WzEyLDFd"}
{"attributes":{"description":"","layerListJSON":"[{\"locale\":\"autoselect\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true,\"lightModeDefault\":\"road_map_desaturated\"},\"id\":\"5ff9c98e-e0d3-4aff-ac98-b33c191496b4\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"EMS_VECTOR_TILE\",\"color\":\"\"},\"includeInFitToBounds\":true,\"type\":\"EMS_VECTOR_TILE\"}]","mapStateJSON":"{\"adHocDataViews\":[],\"zoom\":1.4,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":60000},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"customIcons\":[],\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"keydownScrollZoom\":false,\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"showTimesliderToggleButton\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}","title":"Managed map","uiStateJSON":"{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-24T18:22:40.360Z","id":"managed-d7ab-46eb-a807-8fed28ed8566","managed":true,"references":[],"type":"map","typeMigrationVersion":"8.4.0","updated_at":"2024-01-24T18:23:07.090Z","version":"WzEyLDFd"}
{"attributes":{"description":"","layerListJSON":"[{\"locale\":\"autoselect\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true,\"lightModeDefault\":\"road_map_desaturated\"},\"id\":\"5ff9c98e-e0d3-4aff-ac98-b33c191496b4\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"EMS_VECTOR_TILE\",\"color\":\"\"},\"includeInFitToBounds\":true,\"type\":\"EMS_VECTOR_TILE\"}]","mapStateJSON":"{\"adHocDataViews\":[],\"zoom\":1.4,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":60000},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"customIcons\":[],\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"keydownScrollZoom\":false,\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"showTimesliderToggleButton\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}","title":"Map","uiStateJSON":"{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-24T18:22:40.360Z","id":"unmanaged-d7ab-46eb-a807-8fed28ed8566","managed":false,"references":[],"type":"map","typeMigrationVersion":"8.4.0","updated_at":"2024-01-24T18:23:07.090Z","version":"WzEyLDFd"}
{"attributes":{"description":"","layerListJSON":"[{\"locale\":\"autoselect\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true,\"lightModeDefault\":\"road_map_desaturated\"},\"id\":\"5ff9c98e-e0d3-4aff-ac98-b33c191496b4\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"EMS_VECTOR_TILE\",\"color\":\"\"},\"includeInFitToBounds\":true,\"type\":\"EMS_VECTOR_TILE\"}]","mapStateJSON":"{\"adHocDataViews\":[],\"zoom\":1.4,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":60000},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"customIcons\":[],\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"keydownScrollZoom\":false,\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"showTimesliderToggleButton\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}","title":"Unmanaged map","uiStateJSON":"{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-24T18:22:40.360Z","id":"unmanaged-d7ab-46eb-a807-8fed28ed8566","managed":false,"references":[],"type":"map","typeMigrationVersion":"8.4.0","updated_at":"2024-01-24T18:23:07.090Z","version":"WzEyLDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"536c52e4-ecf1-4cde-9323-cc1c3de1fdd2\"},\"panelIndex\":\"536c52e4-ecf1-4cde-9323-cc1c3de1fdd2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_536c52e4-ecf1-4cde-9323-cc1c3de1fdd2\"},{\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"f19bd0df-03e7-4181-9adf-e3b3b4c97e19\"},\"panelIndex\":\"f19bd0df-03e7-4181-9adf-e3b3b4c97e19\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f19bd0df-03e7-4181-9adf-e3b3b4c97e19\"},{\"type\":\"map\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"26f25c71-2b7c-4540-8c1c-c003b5657978\"},\"panelIndex\":\"26f25c71-2b7c-4540-8c1c-c003b5657978\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":19.94277,\"lon\":0,\"zoom\":1.4},\"mapBuffer\":{\"minLon\":-180,\"minLat\":-66.51326,\"maxLon\":180,\"maxLat\":66.51326},\"isLayerTOCOpen\":true,\"openTOCDetails\":[],\"hiddenLayers\":[],\"enhancements\":{}},\"panelRefName\":\"panel_26f25c71-2b7c-4540-8c1c-c003b5657978\"},{\"type\":\"search\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"d7e33257-de57-40cb-9171-3dd739dd1875\"},\"panelIndex\":\"d7e33257-de57-40cb-9171-3dd739dd1875\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_d7e33257-de57-40cb-9171-3dd739dd1875\"}]","timeRestore":false,"title":"Managed dashboard with by-ref panels","version":1},"coreMigrationVersion":"8.8.0","created_at":"2024-01-31T21:57:49.102Z","id":"c44c86f9-b105-4a9c-9a24-449a58a827f3","managed":true,"references":[{"id":"managed-feb9-4ba6-9538-1b8f67fb4f57","name":"536c52e4-ecf1-4cde-9323-cc1c3de1fdd2:panel_536c52e4-ecf1-4cde-9323-cc1c3de1fdd2","type":"visualization"},{"id":"managed-36db-4a3b-a4ba-7a64ab8f130b","name":"f19bd0df-03e7-4181-9adf-e3b3b4c97e19:panel_f19bd0df-03e7-4181-9adf-e3b3b4c97e19","type":"lens"},{"id":"managed-d7ab-46eb-a807-8fed28ed8566","name":"26f25c71-2b7c-4540-8c1c-c003b5657978:panel_26f25c71-2b7c-4540-8c1c-c003b5657978","type":"map"},{"id":"managed-3d62-4113-ac7c-de2e20a68fbc","name":"d7e33257-de57-40cb-9171-3dd739dd1875:panel_d7e33257-de57-40cb-9171-3dd739dd1875","type":"search"}],"type":"dashboard","typeMigrationVersion":"8.9.0","updated_at":"2024-01-31T21:57:49.102Z","version":"WzEwOSwxXQ=="}

View file

@ -230,22 +230,41 @@ export class DashboardAddPanelService extends FtrService {
return this.addEmbeddable(vizName, 'Visualization');
}
async addEmbeddable(embeddableName: string, embeddableType: string) {
async addEmbeddable(
embeddableName: string,
embeddableType?: string,
closePanelWhenComplete: boolean = true
) {
this.log.debug(
`DashboardAddPanel.addEmbeddable, name: ${embeddableName}, type: ${embeddableType}`
);
await this.ensureAddPanelIsShowing();
await this.savedObjectsFinder.toggleFilter(embeddableType);
await this.savedObjectsFinder.filterEmbeddableNames(`"${embeddableName.replace('-', ' ')}"`);
await this.savedObjectsFinder.filterEmbeddableNames(
`${embeddableType ? 'type:(' + embeddableType + ') ' : ''}"${embeddableName.replace(
'-',
' '
)}"`
);
await this.testSubjects.click(`savedObjectTitle${embeddableName.split(' ').join('-')}`);
await this.testSubjects.exists('addObjectToDashboardSuccess');
if (closePanelWhenComplete) {
await this.closeAddPanel();
}
// close "Added successfully" toast
await this.common.clearAllToasts();
return embeddableName;
}
async addEmbeddables(embeddables: Array<{ name: string; type?: string }>) {
const addedEmbeddables: string[] = [];
for (const { name, type } of embeddables) {
addedEmbeddables.push(await this.addEmbeddable(name, type, false));
}
await this.closeAddPanel();
return addedEmbeddables;
}
async panelAddLinkExists(name: string) {
this.log.debug(`DashboardAddPanel.panelAddLinkExists(${name})`);
await this.ensureAddPanelIsShowing();

View file

@ -8,7 +8,9 @@
import type { CoreStart } from '@kbn/core/public';
import type { AttributeService } from '@kbn/embeddable-plugin/public';
import { OnSaveProps } from '@kbn/saved-objects-plugin/public';
import { SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
import type { LensPluginStartDependencies } from './plugin';
import type { LensSavedObjectAttributes as LensSavedObjectAttributesWithoutReferences } from '../common/content_management';
import type {
LensSavedObjectAttributes,
LensByValueInput,
@ -26,6 +28,16 @@ export type LensAttributeService = AttributeService<
LensUnwrapMetaInfo
>;
export const savedObjectToEmbeddableAttributes = (
savedObject: SavedObjectCommon<LensSavedObjectAttributesWithoutReferences>
): LensSavedObjectAttributes => {
return {
...savedObject.attributes,
state: savedObject.attributes.state as LensSavedObjectAttributes['state'],
references: savedObject.references,
};
};
export function getLensAttributeService(
core: CoreStart,
startDependencies: LensPluginStartDependencies
@ -51,11 +63,7 @@ export function getLensAttributeService(
item: savedObject,
meta: { outcome, aliasTargetId, aliasPurpose },
} = await savedObjectStore.load(savedObjectId);
const { attributes, references, id } = savedObject;
const document = {
...attributes,
references,
};
const { id } = savedObject;
const sharingSavedObjectProps = {
aliasTargetId,
@ -65,10 +73,7 @@ export function getLensAttributeService(
};
return {
attributes: {
...document,
state: document.state as LensSavedObjectAttributes['state'],
},
attributes: savedObjectToEmbeddableAttributes(savedObject),
metaInfo: {
sharingSavedObjectProps,
managed: savedObject.managed,

View file

@ -64,6 +64,7 @@ import {
} from '@kbn/content-management-plugin/public';
import { i18n } from '@kbn/i18n';
import type { ServerlessPluginStart } from '@kbn/serverless/public';
import { registerSavedObjectToPanelMethod } from '@kbn/embeddable-plugin/public';
import type { EditorFrameService as EditorFrameServiceType } from './editor_frame_service';
import type {
FormBasedDatasource as FormBasedDatasourceType,
@ -117,7 +118,7 @@ import { visualizeTSVBAction } from './trigger_actions/visualize_tsvb_actions';
import { visualizeAggBasedVisAction } from './trigger_actions/visualize_agg_based_vis_actions';
import { visualizeDashboardVisualizePanelction } from './trigger_actions/dashboard_visualize_panel_actions';
import type { LensEmbeddableInput } from './embeddable';
import type { LensByValueInput, LensEmbeddableInput } from './embeddable';
import { EmbeddableFactory, LensEmbeddableStartServices } from './embeddable/embeddable_factory';
import { EmbeddableComponent, getEmbeddableComponent } from './embeddable/embeddable_component';
import { getSaveModalComponent } from './app_plugin/shared/saved_modal_lazy';
@ -130,8 +131,13 @@ import { ChartInfoApi } from './chart_info_api';
import { type LensAppLocator, LensAppLocatorDefinition } from '../common/locator/locator';
import { downloadCsvShareProvider } from './app_plugin/csv_download_provider/csv_download_provider';
import { CONTENT_ID, LATEST_VERSION } from '../common/content_management';
import {
CONTENT_ID,
LATEST_VERSION,
LensSavedObjectAttributes,
} from '../common/content_management';
import type { EditLensConfigurationProps } from './app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration';
import { savedObjectToEmbeddableAttributes } from './lens_attribute_service';
export type { SaveProps } from './app_plugin';
@ -424,6 +430,21 @@ export class LensPlugin {
() => startServices().plugins.data.nowProvider.get()
);
registerSavedObjectToPanelMethod<LensSavedObjectAttributes, LensByValueInput>(
CONTENT_ID,
(savedObject) => {
if (!savedObject.managed) {
return { savedObjectId: savedObject.id };
}
const panel = {
attributes: savedObjectToEmbeddableAttributes(savedObject),
};
return panel;
}
);
const getPresentationUtilContext = () =>
startServices().plugins.presentationUtil.ContextProvider;

View file

@ -109,7 +109,8 @@
"@kbn/text-based-editor",
"@kbn/managed-content-badge",
"@kbn/sort-predicates",
"@kbn/presentation-publishing"
"@kbn/presentation-publishing",
"@kbn/saved-objects-finder-plugin"
],
"exclude": ["target/**/*"]
}

View file

@ -9,6 +9,7 @@ import { SavedObjectReference } from '@kbn/core/types';
import type { ResolvedSimpleSavedObject } from '@kbn/core/public';
import { AttributeService } from '@kbn/embeddable-plugin/public';
import type { OnSaveProps } from '@kbn/saved-objects-plugin/public';
import { SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
import type { MapAttributes } from '../common/content_management';
import { MAP_EMBEDDABLE_NAME, MAP_SAVED_OBJECT_TYPE } from '../common/constants';
import { getCoreOverlays, getEmbeddableService } from './kibana_services';
@ -39,6 +40,17 @@ export type MapAttributeService = AttributeService<
MapUnwrapMetaInfo
>;
export const savedObjectToEmbeddableAttributes = (
savedObject: SavedObjectCommon<MapAttributes>
) => {
const { attributes } = injectReferences(savedObject);
return {
...attributes,
references: savedObject.references,
};
};
let mapAttributeService: MapAttributeService | null = null;
export function getMapAttributeService(): MapAttributeService {
@ -90,12 +102,8 @@ export function getMapAttributeService(): MapAttributeService {
throw savedObject.error;
}
const { attributes } = injectReferences(savedObject);
return {
attributes: {
...attributes,
references: savedObject.references,
},
attributes: savedObjectToEmbeddableAttributes(savedObject),
metaInfo: {
sharingSavedObjectProps: {
aliasTargetId,

View file

@ -25,7 +25,11 @@ import type { HomePublicPluginSetup } from '@kbn/home-plugin/public';
import type { VisualizationsSetup, VisualizationsStart } from '@kbn/visualizations-plugin/public';
import type { Plugin as ExpressionsPublicPlugin } from '@kbn/expressions-plugin/public';
import { VISUALIZE_GEO_FIELD_TRIGGER } from '@kbn/ui-actions-plugin/public';
import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public';
import {
EmbeddableSetup,
EmbeddableStart,
registerSavedObjectToPanelMethod,
} from '@kbn/embeddable-plugin/public';
import { CONTEXT_MENU_TRIGGER } from '@kbn/embeddable-plugin/public';
import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
import type { MapsEmsPluginPublicStart } from '@kbn/maps-ems-plugin/public';
@ -82,7 +86,9 @@ import { MapInspectorView } from './inspector/map_adapter/map_inspector_view';
import { VectorTileInspectorView } from './inspector/vector_tile_adapter/vector_tile_inspector_view';
import { setupLensChoroplethChart } from './lens';
import { CONTENT_ID, LATEST_VERSION } from '../common/content_management';
import { CONTENT_ID, LATEST_VERSION, MapAttributes } from '../common/content_management';
import { savedObjectToEmbeddableAttributes } from './map_attribute_service';
import { MapByValueInput } from './embeddable';
export interface MapsPluginSetupDependencies {
cloud?: CloudSetup;
@ -214,6 +220,16 @@ export class MapsPlugin
name: APP_NAME,
});
registerSavedObjectToPanelMethod<MapAttributes, MapByValueInput>(CONTENT_ID, (savedObject) => {
if (!savedObject.managed) {
return { savedObjectId: savedObject.id };
}
return {
attributes: savedObjectToEmbeddableAttributes(savedObject),
};
});
setupLensChoroplethChart(core, plugins.expressions, plugins.lens);
// register wrapper around legacy tile_map and region_map visualizations

View file

@ -85,6 +85,7 @@
"@kbn/code-editor",
"@kbn/managed-content-badge",
"@kbn/presentation-publishing",
"@kbn/saved-objects-finder-plugin",
"@kbn/esql-utils",
],
"exclude": [

View file

@ -16,10 +16,12 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
'common',
'discover',
'maps',
'dashboard',
]);
const kibanaServer = getService('kibanaServer');
const esArchiver = getService('esArchiver');
const testSubjects = getService('testSubjects');
const dashboardAddPanel = getService('dashboardAddPanel');
describe('Managed Content', () => {
before(async () => {
@ -32,6 +34,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/managed_content');
});
describe('preventing the user from overwriting managed content', () => {
const expectManagedContentSignifiers = async (
expected: boolean,
saveButtonTestSubject: string
@ -44,7 +47,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(await saveAsNewCheckbox.getAttribute('disabled')).to.be(expected ? 'true' : null);
};
describe('preventing the user from overwriting managed content', () => {
it('lens', async () => {
await PageObjects.common.navigateToActualUrl(
'lens',
@ -64,7 +66,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await expectManagedContentSignifiers(false, 'lnsApp_saveButton');
});
});
it('discover', async () => {
await PageObjects.common.navigateToActualUrl(
@ -120,4 +121,50 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await expectManagedContentSignifiers(false, 'mapSaveButton');
});
});
describe('managed panels in dashboards', () => {
it('inlines panels when managed dashboard cloned', async () => {
await PageObjects.common.navigateToActualUrl(
'dashboard',
'view/c44c86f9-b105-4a9c-9a24-449a58a827f3'
);
await PageObjects.dashboard.waitForRenderComplete();
await PageObjects.dashboard.clickClone();
await PageObjects.dashboard.waitForRenderComplete();
await testSubjects.missingOrFail('embeddablePanelNotification-ACTION_LIBRARY_NOTIFICATION');
});
it('adds managed panels by-value', async () => {
await PageObjects.common.navigateToApp('dashboard');
await PageObjects.dashboard.gotoDashboardLandingPage();
await PageObjects.dashboard.clickNewDashboard();
await dashboardAddPanel.addEmbeddables([
{ name: 'Managed lens vis', type: 'lens' },
{ name: 'Managed legacy visualization', type: 'visualization' },
{ name: 'Managed map', type: 'map' },
{ name: 'Managed saved search', type: 'search' },
]);
await testSubjects.missingOrFail('embeddablePanelNotification-ACTION_LIBRARY_NOTIFICATION');
await dashboardAddPanel.addEmbeddables([
{ name: 'Unmanaged lens vis', type: 'lens' },
{ name: 'Unmanaged legacy visualization', type: 'visualization' },
{ name: 'Unmanaged map', type: 'map' },
{ name: 'Unmanaged saved search', type: 'search' },
]);
const byRefSignifiers = await testSubjects.findAll(
'embeddablePanelNotification-ACTION_LIBRARY_NOTIFICATION'
);
expect(byRefSignifiers.length).to.be(4);
});
});
});
}