mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Maps] Prevent overwriting managed content from the editor (#175329)
## Summary
Close https://github.com/elastic/kibana/issues/172381
I marked this a breaking change since it is preventing users from doing
something they have been able to do before. They can no longer save
changes to managed map. Instead, they have to save changes to a new map.
To test, import this `ndjson` file which includes a managed map:
<details>
```
{"attributes":{"allowHidden":false,"fieldAttrs":"{}","fieldFormatMap":"{}","fields":"[]","name":"school_neighborhood_poverty_estimates_-_current","runtimeFieldMap":"{}","sourceFilters":"[]","title":"school_neighborhood_poverty_estimates_-_current"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-23T16:29:10.798Z","id":"5162dd45-e7b8-41a4-816d-b427f0be7194","managed":false,"references":[],"type":"index-pattern","typeMigrationVersion":"8.0.0","updated_at":"2024-01-23T16:29:10.798Z","version":"WzYsMV0="}
{"attributes":{"description":"","layerListJSON":"[{\"locale\":\"autoselect\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true,\"lightModeDefault\":\"road_map_desaturated\"},\"id\":\"b093ef75-9c58-4fad-a029-a10f09bafc3e\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"EMS_VECTOR_TILE\",\"color\":\"\"},\"includeInFitToBounds\":true,\"type\":\"EMS_VECTOR_TILE\"},{\"sourceDescriptor\":{\"geoField\":\"geometry\",\"scalingType\":\"MVT\",\"id\":\"47944ba6-77b4-419e-bc90-8443bd86d529\",\"type\":\"ES_SEARCH\",\"applyGlobalQuery\":true,\"applyGlobalTime\":true,\"applyForceRefresh\":true,\"filterByMapBounds\":true,\"tooltipProperties\":[],\"sortField\":\"\",\"sortOrder\":\"desc\",\"topHitsGroupByTimeseries\":false,\"topHitsSplitField\":\"\",\"topHitsSize\":1,\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"id\":\"807664cf-ae19-4b64-8f2e-3d917e35f3ab\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}},\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#54B399\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#41937c\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":0}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":6}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"labelText\":{\"type\":\"STATIC\",\"options\":{\"value\":\"\"}},\"labelColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#000000\"}},\"labelSize\":{\"type\":\"STATIC\",\"options\":{\"size\":14}},\"labelZoomRange\":{\"options\":{\"useLayerZoomRange\":true,\"minZoom\":0,\"maxZoom\":24}},\"labelBorderColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"labelBorderSize\":{\"options\":{\"size\":\"SMALL\"}},\"labelPosition\":{\"options\":{\"position\":\"CENTER\"}}},\"isTimeAware\":true},\"includeInFitToBounds\":true,\"type\":\"MVT_VECTOR\",\"joins\":[],\"disableTooltips\":false}]","mapStateJSON":"{\"adHocDataViews\":[],\"zoom\":9.06,\"center\":{\"lon\":-112.43427,\"lat\":33.76472},\"timeFilters\":{\"from\":\"now-15m\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":60000},\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"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":"My map","uiStateJSON":"{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"},"coreMigrationVersion":"8.8.0","created_at":"2024-01-23T16:27:07.764Z","id":"8359b071-6da7-43dc-b375-3d0afa546763","managed":true,"references":[{"id":"5162dd45-e7b8-41a4-816d-b427f0be7194","name":"layer_1_source_index_pattern","type":"index-pattern"}],"type":"map","typeMigrationVersion":"8.4.0","updated_at":"2024-01-23T16:32:59.750Z","version":"WzcsMV0="}
{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":2,"missingRefCount":0,"missingReferences":[]}
```
</details>
This is how the UI should look:
<img width="1037" alt="Screenshot 2024-01-23 at 9 39 48 AM"
src="45e50364
-d947-486e-9295-f63d56bb7f18">
### 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
- [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/4968
- [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:
parent
25ef250db6
commit
1aea4ba38e
7 changed files with 55 additions and 1 deletions
|
@ -7,3 +7,7 @@
|
|||
{"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":"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":"","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":"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"}
|
||||
|
|
|
@ -28,6 +28,8 @@ type MapDoc = MapAttributes & {
|
|||
};
|
||||
export interface MapUnwrapMetaInfo {
|
||||
sharingSavedObjectProps: SharingSavedObjectProps;
|
||||
// Is this map managed by the system?
|
||||
managed: boolean;
|
||||
}
|
||||
|
||||
export type MapAttributeService = AttributeService<
|
||||
|
@ -101,6 +103,7 @@ export function getMapAttributeService(): MapAttributeService {
|
|||
aliasPurpose,
|
||||
sourceId: savedObjectId,
|
||||
},
|
||||
managed: Boolean(savedObject.managed),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
|
|
@ -32,6 +32,7 @@ import {
|
|||
withNotifyOnErrors,
|
||||
IKbnUrlStateStorage,
|
||||
} from '@kbn/kibana-utils-plugin/public';
|
||||
import { getManagedContentBadge } from '@kbn/managed-content-badge';
|
||||
import {
|
||||
getData,
|
||||
getExecutionContextService,
|
||||
|
@ -486,6 +487,18 @@ export class MapApp extends React.Component<Props, State> {
|
|||
<TopNavMenu
|
||||
setMenuMountPoint={this.props.setHeaderActionMenu}
|
||||
appName={APP_ID}
|
||||
badges={
|
||||
this.props.savedMap.isManaged()
|
||||
? [
|
||||
getManagedContentBadge(
|
||||
i18n.translate('xpack.maps.mapController.managedMapDescriptionTooltip', {
|
||||
defaultMessage:
|
||||
'This map is managed by Elastic. Changes here must be saved to a new map.',
|
||||
})
|
||||
),
|
||||
]
|
||||
: undefined
|
||||
}
|
||||
config={topNavConfig}
|
||||
indexPatterns={this.state.indexPatterns}
|
||||
filters={this.props.filters}
|
||||
|
|
|
@ -85,6 +85,7 @@ export class SavedMap {
|
|||
private readonly _store: MapStore;
|
||||
private _tags: string[] = [];
|
||||
private _defaultLayerWizard: string;
|
||||
private _managed: boolean;
|
||||
|
||||
constructor({
|
||||
defaultLayers = [],
|
||||
|
@ -114,6 +115,7 @@ export class SavedMap {
|
|||
this._stateTransfer = stateTransfer;
|
||||
this._store = createMapStore();
|
||||
this._defaultLayerWizard = defaultLayerWizard || '';
|
||||
this._managed = false;
|
||||
}
|
||||
|
||||
public getStore() {
|
||||
|
@ -137,6 +139,7 @@ export class SavedMap {
|
|||
if (metaInfo?.sharingSavedObjectProps) {
|
||||
this._sharingSavedObjectProps = metaInfo.sharingSavedObjectProps;
|
||||
}
|
||||
this._managed = Boolean(metaInfo?.managed);
|
||||
const savedObjectsTagging = getSavedObjectsTagging();
|
||||
if (savedObjectsTagging && references && references.length) {
|
||||
this._tags = savedObjectsTagging.ui.getTagIdsFromReferences(references);
|
||||
|
@ -430,6 +433,10 @@ export class SavedMap {
|
|||
return this._sharingSavedObjectProps;
|
||||
}
|
||||
|
||||
public isManaged(): boolean {
|
||||
return this._managed;
|
||||
}
|
||||
|
||||
public isByValue(): boolean {
|
||||
const hasSavedObjectId = !!this.getSavedObjectId();
|
||||
return getIsAllowByValueEmbeddables() && !!this._originatingApp && !hasSavedObjectId;
|
||||
|
|
|
@ -240,6 +240,14 @@ export function getTopNavConfig({
|
|||
<SavedObjectSaveModalDashboard
|
||||
{...saveModalProps}
|
||||
canSaveByReference={true} // we know here that we have save capabilities.
|
||||
mustCopyOnSaveMessage={
|
||||
savedMap.isManaged()
|
||||
? i18n.translate('xpack.maps.topNav.mustCopyOnSaveMessage', {
|
||||
defaultMessage:
|
||||
'This map is managed by Elastic. Changes here must be saved to a new map.',
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
tagOptions={tagSelector}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
"@kbn/es-types",
|
||||
"@kbn/data-service",
|
||||
"@kbn/code-editor",
|
||||
"@kbn/managed-content-badge",
|
||||
"@kbn/presentation-publishing",
|
||||
],
|
||||
"exclude": [
|
||||
|
|
|
@ -9,7 +9,7 @@ import expect from '@kbn/expect';
|
|||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||
const PageObjects = getPageObjects(['timePicker', 'lens', 'common', 'discover']);
|
||||
const PageObjects = getPageObjects(['timePicker', 'lens', 'common', 'discover', 'maps']);
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
@ -76,5 +76,23 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
|
||||
await expectManagedContentSignifiers(false, 'discoverSaveButton');
|
||||
});
|
||||
|
||||
it('maps', async () => {
|
||||
await PageObjects.common.navigateToActualUrl(
|
||||
'maps',
|
||||
'map/managed-d7ab-46eb-a807-8fed28ed8566'
|
||||
);
|
||||
await PageObjects.maps.waitForLayerAddPanelClosed();
|
||||
|
||||
await expectManagedContentSignifiers(true, 'mapSaveButton');
|
||||
|
||||
await PageObjects.common.navigateToActualUrl(
|
||||
'maps',
|
||||
'map/unmanaged-d7ab-46eb-a807-8fed28ed8566'
|
||||
);
|
||||
await PageObjects.maps.waitForLayerAddPanelClosed();
|
||||
|
||||
await expectManagedContentSignifiers(false, 'mapSaveButton');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue