From 0e311689fee3a8fc118291b60e9038c5b09aa414 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 20 Sep 2021 13:43:14 -0600 Subject: [PATCH 1/8] [Maps] Switch to SavedObjectClient.resolve --- x-pack/plugins/maps/kibana.json | 1 + .../maps/public/embeddable/_index.scss | 8 +++ .../maps/public/embeddable/map_embeddable.tsx | 38 ++++++++---- x-pack/plugins/maps/public/kibana_services.ts | 1 + .../maps/public/map_attribute_service.ts | 35 ++++++++++- x-pack/plugins/maps/public/plugin.ts | 4 +- .../routes/map_page/map_app/map_app.tsx | 18 +++++- .../routes/map_page/saved_map/saved_map.ts | 10 ++- x-pack/plugins/maps/tsconfig.json | 3 +- .../get_saved_object_conflict_message.tsx | 17 +++++ .../components/index.ts | 1 + .../saved_object_conflict_message.tsx | 62 +++++++++++++++++++ .../share_saved_objects_to_space/index.ts | 2 +- .../spaces/public/ui_api/components.tsx | 2 + 14 files changed, 181 insertions(+), 21 deletions(-) create mode 100644 x-pack/plugins/spaces/public/share_saved_objects_to_space/components/get_saved_object_conflict_message.tsx create mode 100644 x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx diff --git a/x-pack/plugins/maps/kibana.json b/x-pack/plugins/maps/kibana.json index bfd501dbcb295..2aa2e4a756490 100644 --- a/x-pack/plugins/maps/kibana.json +++ b/x-pack/plugins/maps/kibana.json @@ -29,6 +29,7 @@ "savedObjectsTagging", "charts", "security", + "spaces", "usageCollection" ], "ui": true, diff --git a/x-pack/plugins/maps/public/embeddable/_index.scss b/x-pack/plugins/maps/public/embeddable/_index.scss index 966236f54d259..07c874d966fec 100644 --- a/x-pack/plugins/maps/public/embeddable/_index.scss +++ b/x-pack/plugins/maps/public/embeddable/_index.scss @@ -5,4 +5,12 @@ flex: 1 1 100%; z-index: 1; min-height: 0; // Absolute must for Firefox to scroll contents +} + +.mapEmbeddedError { + flex-grow: 1; + display: flex; + align-items: center; + justify-content: center; + overflow: auto; } \ No newline at end of file diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx index c15138f6c5b15..21a472c029410 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx @@ -12,6 +12,7 @@ import { Provider } from 'react-redux'; import { render, unmountComponentAtNode } from 'react-dom'; import { Subscription } from 'rxjs'; import { Unsubscribe } from 'redux'; +import { EuiEmptyPrompt } from '@elastic/eui'; import { Embeddable, IContainer, @@ -66,6 +67,7 @@ import { getCoreI18n, getHttp, getChartsPaletteServiceGetColor, + getSpacesApi, getSearchService, } from '../kibana_services'; import { LayerDescriptor, MapExtent } from '../../common/descriptor_types'; @@ -353,22 +355,34 @@ export class MapEmbeddable return; } - const I18nContext = getCoreI18n().Context; + const sharingSavedObjectProps = this._savedMap.getSharingSavedObjectProps(); + const spaces = getSpacesApi(); + const content = sharingSavedObjectProps && spaces && sharingSavedObjectProps?.outcome === 'conflict' + ?
+ +
+ : ; + const I18nContext = getCoreI18n().Context; render( - + {content} , this._domNode diff --git a/x-pack/plugins/maps/public/kibana_services.ts b/x-pack/plugins/maps/public/kibana_services.ts index 300fe07a841e9..5ad3a1d3fd23d 100644 --- a/x-pack/plugins/maps/public/kibana_services.ts +++ b/x-pack/plugins/maps/public/kibana_services.ts @@ -53,6 +53,7 @@ export const getNavigateToApp = () => coreStart.application.navigateToApp; export const getSavedObjectsTagging = () => pluginsStart.savedObjectsTagging; export const getPresentationUtilContext = () => pluginsStart.presentationUtil.ContextProvider; export const getSecurityService = () => pluginsStart.security; +export const getSpacesApi = () => pluginsStart.spaces; // xpack.maps.* kibana.yml settings from this plugin let mapAppConfig: MapsConfigType; diff --git a/x-pack/plugins/maps/public/map_attribute_service.ts b/x-pack/plugins/maps/public/map_attribute_service.ts index 5f7c45b1b42d7..72544f25c52cc 100644 --- a/x-pack/plugins/maps/public/map_attribute_service.ts +++ b/x-pack/plugins/maps/public/map_attribute_service.ts @@ -14,8 +14,18 @@ import { checkForDuplicateTitle, OnSaveProps } from '../../../../src/plugins/sav import { getCoreOverlays, getEmbeddableService, getSavedObjectsClient } from './kibana_services'; import { extractReferences, injectReferences } from '../common/migrations/references'; import { MapByValueInput, MapByReferenceInput } from './embeddable/types'; +import { getSpacesApi } from './kibana_services'; -type MapDoc = MapSavedObjectAttributes & { references?: SavedObjectReference[] }; +interface SharingSavedObjectProps { + outcome?: 'aliasMatch' | 'exactMatch' | 'conflict'; + aliasTargetId?: string; + errorJSON?: string; +} + +type MapDoc = MapSavedObjectAttributes & { + sharingSavedObjectProps?: SharingSavedObjectProps; + references?: SavedObjectReference[]; +}; export type MapAttributeService = AttributeService; @@ -58,7 +68,11 @@ export function getMapAttributeService(): MapAttributeService { return { id: savedObject.id }; }, unwrapMethod: async (savedObjectId: string): Promise => { - const savedObject = await getSavedObjectsClient().get( + const { + saved_object: savedObject, + outcome, + alias_target_id: aliasTargetId, + } = await getSavedObjectsClient().resolve( MAP_SAVED_OBJECT_TYPE, savedObjectId ); @@ -68,7 +82,22 @@ export function getMapAttributeService(): MapAttributeService { } const { attributes } = injectReferences(savedObject); - return { ...attributes, references: savedObject.references }; + return { + ...attributes, + references: savedObject.references, + sharingSavedObjectProps: { + aliasTargetId, + outcome, + errorJSON: + outcome === 'conflict' && getSpacesApi() + ? JSON.stringify({ + targetType: MAP_SAVED_OBJECT_TYPE, + sourceId: savedObjectId, + targetSpace: (await getSpacesApi().getActiveSpace()).id, + }) + : undefined, + } + }; }, checkForDuplicateTitle: (props: OnSaveProps) => { return checkForDuplicateTitle( diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 784f4e8f4b9d9..f26b1972cd513 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -82,7 +82,8 @@ import { tileMapRenderer, tileMapVisType, } from './legacy_visualizations'; -import { SecurityPluginStart } from '../../security/public'; +import type { SecurityPluginStart } from '../../security/public'; +import type { SpacesPluginStart } from '../../spaces/public'; export interface MapsPluginSetupDependencies { expressions: ReturnType; @@ -112,6 +113,7 @@ export interface MapsPluginStartDependencies { savedObjectsTagging?: SavedObjectTaggingPluginStart; presentationUtil: PresentationUtilPluginStart; security: SecurityPluginStart; + spaces?: SpacesPluginStart; } /** diff --git a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx index 212fa89e2ad65..a254a5ae4d376 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx @@ -18,6 +18,7 @@ import { getCoreChrome, getMapsCapabilities, getNavigation, + getSpacesApi, getTimeFilter, getToasts, } from '../../../kibana_services'; @@ -40,7 +41,8 @@ import { getIndexPatternsFromIds } from '../../../index_pattern_util'; import { getTopNavConfig } from '../top_nav_config'; import { goToSpecifiedPath } from '../../../render_app'; import { MapSavedObjectAttributes } from '../../../../common/map_saved_object_type'; -import { getFullPath, APP_ID } from '../../../../common/constants'; +import { getEditPath, getFullPath, APP_ID } from '../../../../common/constants'; +import { getMapEmbeddableDisplayName } from '../../../../common/i18n_getters'; import { getInitialQuery, getInitialRefreshConfig, @@ -437,6 +439,19 @@ export class MapApp extends React.Component { this._onFiltersChange([...this.props.filters, ...newFilters]); }; + _renderLegacyUrlConflict() { + const sharingSavedObjectProps = this.props.savedMap.getSharingSavedObjectProps(); + const spaces = getSpacesApi(); + return sharingSavedObjectProps && spaces && sharingSavedObjectProps?.outcome === 'conflict' + ? spaces.ui.components.getLegacyUrlConflict({ + objectNoun: getMapEmbeddableDisplayName(), + currentObjectId: this.props.savedMap.getSavedObjectId()!, + otherObjectId: sharingSavedObjectProps.aliasTargetId!, + otherObjectPath: getEditPath(sharingSavedObjectProps.aliasTargetId!), + }) + : null; + } + render() { if (!this.state.initialized) { return null; @@ -447,6 +462,7 @@ export class MapApp extends React.Component { {this._renderTopNav()}

{`screenTitle placeholder`}

+ {this._renderLegacyUrlConflict()} > => { + const { SavedObjectConflictMessage } = await import('./saved_object_conflict_message'); + return (props: Props) => { + return ; + }; +}; diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/index.ts b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/index.ts index c0828e3b5331d..fa641d03fd715 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/index.ts +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/index.ts @@ -6,4 +6,5 @@ */ export { getShareToSpaceFlyoutComponent } from './share_to_space_flyout'; +export { getSavedObjectConflictMessage } from './get_saved_object_conflict_message'; export { getLegacyUrlConflict } from './legacy_url_conflict'; diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx new file mode 100644 index 0000000000000..b76052697a861 --- /dev/null +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx @@ -0,0 +1,62 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiButtonEmpty, + EuiCallOut, + EuiSpacer, + EuiLink, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +export interface Props { + json: string; +} + +export const SavedObjectConflictMessage = ({ json }: Props) => { + const [expandError, setExpandError] = useState(false); + return ( + <> + + {i18n.translate('xpack.spaces.legacyURLConflict.documentationLinkText', { + defaultMessage: 'legacy URL alias', + })} + + ), + }} + /> + + {expandError ? ( + + ) : ( + setExpandError(true)}> + {i18n.translate('xpack.spaces.legacyURLConflict.expandError', { + defaultMessage: `Show more`, + })} + + )} + + ); +}; \ No newline at end of file diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts b/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts index fe90ee8d6a8a9..82a3f1bc32aa7 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -export { getShareToSpaceFlyoutComponent, getLegacyUrlConflict } from './components'; +export { getShareToSpaceFlyoutComponent, getLegacyUrlConflict, getSavedObjectConflictMessage } from './components'; export { createRedirectLegacyUrl } from './utils'; export type { LegacyUrlConflictProps, diff --git a/x-pack/plugins/spaces/public/ui_api/components.tsx b/x-pack/plugins/spaces/public/ui_api/components.tsx index a33480712ffae..71dc2e34a0d70 100644 --- a/x-pack/plugins/spaces/public/ui_api/components.tsx +++ b/x-pack/plugins/spaces/public/ui_api/components.tsx @@ -14,6 +14,7 @@ import { getCopyToSpaceFlyoutComponent } from '../copy_saved_objects_to_space'; import type { PluginsStart } from '../plugin'; import { getLegacyUrlConflict, + getSavedObjectConflictMessage, getShareToSpaceFlyoutComponent, } from '../share_saved_objects_to_space'; import { getSpaceAvatarComponent } from '../space_avatar'; @@ -56,5 +57,6 @@ export const getComponents = ({ getSpaceList: wrapLazy(getSpaceListComponent), getLegacyUrlConflict: wrapLazy(() => getLegacyUrlConflict({ getStartServices })), getSpaceAvatar: wrapLazy(getSpaceAvatarComponent), + getSavedObjectConflictMessage: wrapLazy(() => getSavedObjectConflictMessage()), }; }; From ad791b49e02eefee81598920c5dc9f7797bf4213 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 20 Sep 2021 14:27:51 -0600 Subject: [PATCH 2/8] spaces tslint --- x-pack/plugins/spaces/public/mocks.ts | 1 + .../components/get_saved_object_conflict_message.tsx | 6 +++--- .../components/saved_object_conflict_message.tsx | 7 ++----- .../spaces/public/share_saved_objects_to_space/index.ts | 1 + .../spaces/public/share_saved_objects_to_space/types.ts | 7 +++++++ x-pack/plugins/spaces/public/ui_api/types.ts | 5 +++++ 6 files changed, 19 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/spaces/public/mocks.ts b/x-pack/plugins/spaces/public/mocks.ts index 897f58e1d649c..76cafd4c7f5ae 100644 --- a/x-pack/plugins/spaces/public/mocks.ts +++ b/x-pack/plugins/spaces/public/mocks.ts @@ -41,6 +41,7 @@ const createApiUiComponentsMock = () => { getSpaceList: jest.fn(), getLegacyUrlConflict: jest.fn(), getSpaceAvatar: jest.fn(), + getSavedObjectConflictMessage: jest.fn(), }; return mock; diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/get_saved_object_conflict_message.tsx b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/get_saved_object_conflict_message.tsx index 03ab766766e0f..ef7c4458d8e75 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/get_saved_object_conflict_message.tsx +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/get_saved_object_conflict_message.tsx @@ -7,11 +7,11 @@ import React from 'react'; -import type { Props } from './saved_object_conflict_message'; +import type { SavedObjectConflictMessageProps } from '../types'; -export const getSavedObjectConflictMessage = async (): Promise> => { +export const getSavedObjectConflictMessage = async (): Promise> => { const { SavedObjectConflictMessage } = await import('./saved_object_conflict_message'); - return (props: Props) => { + return (props: SavedObjectConflictMessageProps) => { return ; }; }; diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx index b76052697a861..72fbcfb271618 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx @@ -14,12 +14,9 @@ import { EuiLink, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { SavedObjectConflictMessageProps } from '../types'; -export interface Props { - json: string; -} - -export const SavedObjectConflictMessage = ({ json }: Props) => { +export const SavedObjectConflictMessage = ({ json }: SavedObjectConflictMessageProps) => { const [expandError, setExpandError] = useState(false); return ( <> diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts b/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts index 82a3f1bc32aa7..93b9c425441ba 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts @@ -11,4 +11,5 @@ export type { LegacyUrlConflictProps, ShareToSpaceFlyoutProps, ShareToSpaceSavedObjectTarget, + SavedObjectConflictMessageProps, } from './types'; diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/types.ts b/x-pack/plugins/spaces/public/share_saved_objects_to_space/types.ts index 1beccaa546282..21290f2b90de5 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/types.ts +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/types.ts @@ -140,3 +140,10 @@ export interface ShareToSpaceSavedObjectTarget { */ noun?: string; } + +/** + * Properties for the SavedObjectConflictMessage component. + */ +export interface SavedObjectConflictMessageProps { + json: string; +} diff --git a/x-pack/plugins/spaces/public/ui_api/types.ts b/x-pack/plugins/spaces/public/ui_api/types.ts index 5048e5a9b9652..7a845e8d4f09a 100644 --- a/x-pack/plugins/spaces/public/ui_api/types.ts +++ b/x-pack/plugins/spaces/public/ui_api/types.ts @@ -13,6 +13,7 @@ import type { CopyToSpaceFlyoutProps } from '../copy_saved_objects_to_space'; import type { LegacyUrlConflictProps, ShareToSpaceFlyoutProps, + SavedObjectConflictMessageProps, } from '../share_saved_objects_to_space'; import type { SpaceAvatarProps } from '../space_avatar'; import type { SpaceListProps } from '../space_list'; @@ -109,4 +110,8 @@ export interface SpacesApiUiComponent { * Displays an avatar for the given space. */ getSpaceAvatar: LazyComponentFn; + /** + * Displays a saved object conflict message that directs user to disable legacy URL alias + */ + getSavedObjectConflictMessage: LazyComponentFn; } From 48833e124d04b11b17a9798403218b8516532d08 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 20 Sep 2021 14:51:27 -0600 Subject: [PATCH 3/8] aliasMatch --- .../maps/public/map_attribute_service.ts | 4 ++-- x-pack/plugins/maps/public/render_app.tsx | 3 ++- .../public/routes/map_page/map_app/map_app.tsx | 17 +++++++++++++++++ .../maps/public/routes/map_page/map_page.tsx | 6 ++++-- .../routes/map_page/saved_map/saved_map.ts | 4 +++- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/maps/public/map_attribute_service.ts b/x-pack/plugins/maps/public/map_attribute_service.ts index 72544f25c52cc..56afe831ab14c 100644 --- a/x-pack/plugins/maps/public/map_attribute_service.ts +++ b/x-pack/plugins/maps/public/map_attribute_service.ts @@ -16,7 +16,7 @@ import { extractReferences, injectReferences } from '../common/migrations/refere import { MapByValueInput, MapByReferenceInput } from './embeddable/types'; import { getSpacesApi } from './kibana_services'; -interface SharingSavedObjectProps { +export interface SharingSavedObjectProps { outcome?: 'aliasMatch' | 'exactMatch' | 'conflict'; aliasTargetId?: string; errorJSON?: string; @@ -93,7 +93,7 @@ export function getMapAttributeService(): MapAttributeService { ? JSON.stringify({ targetType: MAP_SAVED_OBJECT_TYPE, sourceId: savedObjectId, - targetSpace: (await getSpacesApi().getActiveSpace()).id, + targetSpace: (await getSpacesApi()!.getActiveSpace()).id, }) : undefined, } diff --git a/x-pack/plugins/maps/public/render_app.tsx b/x-pack/plugins/maps/public/render_app.tsx index de67939b1a42a..3eefaeb6f7a9b 100644 --- a/x-pack/plugins/maps/public/render_app.tsx +++ b/x-pack/plugins/maps/public/render_app.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Router, Switch, Route, Redirect, RouteComponentProps } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; -import { AppMountParameters } from 'kibana/public'; +import type { AppMountParameters } from 'kibana/public'; import { getCoreChrome, getCoreI18n, @@ -98,6 +98,7 @@ export async function renderApp( setHeaderActionMenu={setHeaderActionMenu} stateTransfer={stateTransfer} originatingApp={originatingApp} + history={history} key={routeProps.match.params.savedMapId ? routeProps.match.params.savedMapId : 'new'} /> ); diff --git a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx index a254a5ae4d376..8a0b8c3bf7009 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx @@ -16,6 +16,7 @@ import type { Query, Filter, TimeRange, IndexPattern } from 'src/plugins/data/co import { getData, getCoreChrome, + getHttp, getMapsCapabilities, getNavigation, getSpacesApi, @@ -87,6 +88,7 @@ export interface Props { isSaveDisabled: boolean; query: Query | undefined; setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; + history: AppMountParameters['history']; } export interface State { @@ -349,6 +351,21 @@ export class MapApp extends React.Component { return; } + const sharingSavedObjectProps = this.props.savedMap.getSharingSavedObjectProps(); + const spaces = getSpacesApi(); + if (spaces && sharingSavedObjectProps?.outcome === 'aliasMatch') { + // We found this object by a legacy URL alias from its old ID; redirect the user to the page with its new ID, preserving any URL hash + const newObjectId = sharingSavedObjectProps?.aliasTargetId; // This is always defined if outcome === 'aliasMatch' + const newPath = getHttp().basePath.prepend( + `${getFullPath(newObjectId)}${this.props.history.location.search}` + ); + await spaces.ui.redirectLegacyUrl( + newPath, + getMapEmbeddableDisplayName() + ); + return; + } + this.props.savedMap.setBreadcrumbs(); getCoreChrome().docTitle.change(this.props.savedMap.getTitle()); const savedObjectId = this.props.savedMap.getSavedObjectId(); diff --git a/x-pack/plugins/maps/public/routes/map_page/map_page.tsx b/x-pack/plugins/maps/public/routes/map_page/map_page.tsx index 73ea62ef59d7c..7e927115a5d06 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_page.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/map_page.tsx @@ -7,8 +7,8 @@ import React, { Component } from 'react'; import { Provider } from 'react-redux'; -import { AppMountParameters } from 'kibana/public'; -import { EmbeddableStateTransfer } from 'src/plugins/embeddable/public'; +import type { AppMountParameters } from 'kibana/public'; +import type { EmbeddableStateTransfer } from 'src/plugins/embeddable/public'; import { MapApp } from './map_app'; import { SavedMap, getInitialLayersFromUrlParam } from './saved_map'; import { MapEmbeddableInput } from '../../embeddable/types'; @@ -20,6 +20,7 @@ interface Props { setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; stateTransfer: EmbeddableStateTransfer; originatingApp?: string; + history: AppMountParameters['history']; } interface State { @@ -69,6 +70,7 @@ export class MapPage extends Component { return ( Date: Mon, 20 Sep 2021 15:04:44 -0600 Subject: [PATCH 4/8] maps eslint --- .../maps/public/embeddable/map_embeddable.tsx | 19 +++++++++++-------- .../maps/public/map_attribute_service.ts | 4 ++-- .../routes/map_page/map_app/map_app.tsx | 5 +---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx index 21a472c029410..b0daace7afa9e 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx @@ -357,16 +357,20 @@ export class MapEmbeddable const sharingSavedObjectProps = this._savedMap.getSharingSavedObjectProps(); const spaces = getSpacesApi(); - const content = sharingSavedObjectProps && spaces && sharingSavedObjectProps?.outcome === 'conflict' - ?
+ const content = + sharingSavedObjectProps && spaces && sharingSavedObjectProps?.outcome === 'conflict' ? ( +
- : ; + /> + ); const I18nContext = getCoreI18n().Context; render( - - {content} - + {content} , this._domNode ); diff --git a/x-pack/plugins/maps/public/map_attribute_service.ts b/x-pack/plugins/maps/public/map_attribute_service.ts index 56afe831ab14c..ab380ca5a6b66 100644 --- a/x-pack/plugins/maps/public/map_attribute_service.ts +++ b/x-pack/plugins/maps/public/map_attribute_service.ts @@ -24,7 +24,7 @@ export interface SharingSavedObjectProps { type MapDoc = MapSavedObjectAttributes & { sharingSavedObjectProps?: SharingSavedObjectProps; - references?: SavedObjectReference[]; + references?: SavedObjectReference[]; }; export type MapAttributeService = AttributeService; @@ -96,7 +96,7 @@ export function getMapAttributeService(): MapAttributeService { targetSpace: (await getSpacesApi()!.getActiveSpace()).id, }) : undefined, - } + }, }; }, checkForDuplicateTitle: (props: OnSaveProps) => { diff --git a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx index 8a0b8c3bf7009..0fa0de114f57d 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx @@ -359,10 +359,7 @@ export class MapApp extends React.Component { const newPath = getHttp().basePath.prepend( `${getFullPath(newObjectId)}${this.props.history.location.search}` ); - await spaces.ui.redirectLegacyUrl( - newPath, - getMapEmbeddableDisplayName() - ); + await spaces.ui.redirectLegacyUrl(newPath, getMapEmbeddableDisplayName()); return; } From 6818d31714efcaf0a6c791d73d1c732438497ea0 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 20 Sep 2021 15:17:36 -0600 Subject: [PATCH 5/8] update lens to use spaces.ui.components.getSavedObjectConflictMessage --- .../lens/public/embeddable/embeddable.tsx | 17 +++++- .../public/embeddable/embeddable_factory.ts | 4 ++ .../public/embeddable/expression_wrapper.tsx | 56 +------------------ x-pack/plugins/lens/public/plugin.ts | 1 + 4 files changed, 20 insertions(+), 58 deletions(-) diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index 263198871f07a..0244e84c57a27 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -7,6 +7,7 @@ import { isEqual, uniqBy } from 'lodash'; import React from 'react'; +import { i18n } from '@kbn/i18n'; import { render, unmountComponentAtNode } from 'react-dom'; import type { ExecutionContextSearch, @@ -44,7 +45,6 @@ import { Document, injectFilterReferences } from '../persistence'; import { ExpressionWrapper, ExpressionWrapperProps, - savedObjectConflictError, } from './expression_wrapper'; import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; import { @@ -63,6 +63,7 @@ import { LensAttributeService } from '../lens_attribute_service'; import type { ErrorMessage } from '../editor_frame_service/types'; import { getLensInspectorService, LensInspector } from '../lens_inspector_service'; import { SharingSavedObjectProps } from '../types'; +import type { SpacesPluginStart } from '../../../spaces/public'; export type LensSavedObjectAttributes = Omit; export interface ResolvedLensSavedObjectAttributes extends LensSavedObjectAttributes { @@ -108,6 +109,7 @@ export interface LensEmbeddableDeps { getTriggerCompatibleActions?: UiActionsStart['getTriggerCompatibleActions']; capabilities: { canSaveVisualizations: boolean; canSaveDashboards: boolean }; usageCollection?: UsageCollectionSetup; + spaces?: SpacesPluginStart; } export class Embeddable @@ -281,8 +283,17 @@ export class Embeddable }; const { ast, errors } = await this.deps.documentToExpression(this.savedVis); this.errors = errors; - if (sharingSavedObjectProps?.outcome === 'conflict') { - const conflictError = savedObjectConflictError(sharingSavedObjectProps.errorJSON!); + if (sharingSavedObjectProps?.outcome === 'conflict' && this.deps.spaces) { + const conflictError = { + shortMessage: i18n.translate('xpack.lens.embeddable.legacyURLConflict.shortMessage', { + defaultMessage: `You've encountered a URL conflict`, + }), + longMessage: ( + + ), + }; this.errors = this.errors ? [...this.errors, conflictError] : [conflictError]; } this.expression = ast ? toExpression(ast) : null; diff --git a/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts b/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts index 954905c51a4b7..e51ec4c3e5588 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts +++ b/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts @@ -24,6 +24,7 @@ import { LensAttributeService } from '../lens_attribute_service'; import { DOC_TYPE } from '../../common/constants'; import { ErrorMessage } from '../editor_frame_service/types'; import { extract, inject } from '../../common/embeddable_factory'; +import type { SpacesPluginStart } from '../../../spaces/public'; export interface LensEmbeddableStartServices { timefilter: TimefilterContract; @@ -38,6 +39,7 @@ export interface LensEmbeddableStartServices { documentToExpression: ( doc: Document ) => Promise<{ ast: Ast | null; errors: ErrorMessage[] | undefined }>; + spaces?: SpacesPluginStart; } export class EmbeddableFactory implements EmbeddableFactoryDefinition { @@ -90,6 +92,7 @@ export class EmbeddableFactory implements EmbeddableFactoryDefinition { capabilities, usageCollection, inspector, + spaces, } = await this.getStartServices(); const { Embeddable } = await import('../async_services'); @@ -110,6 +113,7 @@ export class EmbeddableFactory implements EmbeddableFactoryDefinition { canSaveVisualizations: Boolean(capabilities.visualize.save), }, usageCollection, + spaces, }, input, parent diff --git a/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx b/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx index c827fe74cc52b..ba5e806a37bc9 100644 --- a/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx +++ b/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useState } from 'react'; +import React from 'react'; import { I18nProvider } from '@kbn/i18n/react'; import { FormattedMessage } from '@kbn/i18n/react'; import { @@ -14,10 +14,6 @@ import { EuiText, EuiIcon, EuiEmptyPrompt, - EuiButtonEmpty, - EuiCallOut, - EuiSpacer, - EuiLink, } from '@elastic/eui'; import { ExpressionRendererEvent, @@ -28,7 +24,6 @@ import type { KibanaExecutionContext } from 'src/core/public'; import { ExecutionContextSearch } from 'src/plugins/data/public'; import { DefaultInspectorAdapters, RenderMode } from 'src/plugins/expressions'; import classNames from 'classnames'; -import { i18n } from '@kbn/i18n'; import { getOriginalRequestErrorMessages } from '../editor_frame_service/error_helper'; import { ErrorMessage } from '../editor_frame_service/types'; import { LensInspector } from '../lens_inspector_service'; @@ -172,52 +167,3 @@ export function ExpressionWrapper({ ); } - -const SavedObjectConflictMessage = ({ json }: { json: string }) => { - const [expandError, setExpandError] = useState(false); - return ( - <> - - {i18n.translate('xpack.lens.embeddable.legacyURLConflict.documentationLinkText', { - defaultMessage: 'legacy URL alias', - })} - - ), - }} - /> - - {expandError ? ( - - ) : ( - setExpandError(true)}> - {i18n.translate('xpack.lens.embeddable.legacyURLConflict.expandError', { - defaultMessage: `Show more`, - })} - - )} - - ); -}; - -export const savedObjectConflictError = (json: string): ErrorMessage => ({ - shortMessage: i18n.translate('xpack.lens.embeddable.legacyURLConflict.shortMessage', { - defaultMessage: `You've encountered a URL conflict`, - }), - longMessage: , -}); diff --git a/x-pack/plugins/lens/public/plugin.ts b/x-pack/plugins/lens/public/plugin.ts index 5326927d2c6c5..fd0f528ec3910 100644 --- a/x-pack/plugins/lens/public/plugin.ts +++ b/x-pack/plugins/lens/public/plugin.ts @@ -212,6 +212,7 @@ export class LensPlugin { uiActions: plugins.uiActions, usageCollection, inspector: plugins.inspector, + spaces: plugins.spaces, }; }; From e42301d28222a1b1617d81d4ab7472ace5cb5c6b Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 20 Sep 2021 15:30:03 -0600 Subject: [PATCH 6/8] lens eslint --- x-pack/plugins/lens/public/embeddable/embeddable.tsx | 5 +---- .../plugins/lens/public/embeddable/expression_wrapper.tsx | 8 +------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index 0244e84c57a27..2e0ab2401c70f 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -42,10 +42,7 @@ import { ReferenceOrValueEmbeddable, } from '../../../../../src/plugins/embeddable/public'; import { Document, injectFilterReferences } from '../persistence'; -import { - ExpressionWrapper, - ExpressionWrapperProps, -} from './expression_wrapper'; +import { ExpressionWrapper, ExpressionWrapperProps } from './expression_wrapper'; import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; import { isLensBrushEvent, diff --git a/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx b/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx index ba5e806a37bc9..3de914d13d69d 100644 --- a/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx +++ b/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx @@ -8,13 +8,7 @@ import React from 'react'; import { I18nProvider } from '@kbn/i18n/react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiText, - EuiIcon, - EuiEmptyPrompt, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiText, EuiIcon, EuiEmptyPrompt } from '@elastic/eui'; import { ExpressionRendererEvent, ReactExpressionRendererType, From c3900568d1c49dd481e67b3a67d4a39ecbd7e0b9 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 20 Sep 2021 16:52:16 -0600 Subject: [PATCH 7/8] spaces eslint --- .../components/get_saved_object_conflict_message.tsx | 4 +++- .../components/saved_object_conflict_message.tsx | 11 ++++------- .../public/share_saved_objects_to_space/index.ts | 6 +++++- x-pack/plugins/spaces/public/ui_api/types.ts | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/get_saved_object_conflict_message.tsx b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/get_saved_object_conflict_message.tsx index ef7c4458d8e75..66b2a5652057a 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/get_saved_object_conflict_message.tsx +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/get_saved_object_conflict_message.tsx @@ -9,7 +9,9 @@ import React from 'react'; import type { SavedObjectConflictMessageProps } from '../types'; -export const getSavedObjectConflictMessage = async (): Promise> => { +export const getSavedObjectConflictMessage = async (): Promise< + React.FC +> => { const { SavedObjectConflictMessage } = await import('./saved_object_conflict_message'); return (props: SavedObjectConflictMessageProps) => { return ; diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx index 72fbcfb271618..22a1ad7cd20aa 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/saved_object_conflict_message.tsx @@ -5,15 +5,12 @@ * 2.0. */ +import { EuiButtonEmpty, EuiCallOut, EuiLink, EuiSpacer } from '@elastic/eui'; import React, { useState } from 'react'; + import { i18n } from '@kbn/i18n'; -import { - EuiButtonEmpty, - EuiCallOut, - EuiSpacer, - EuiLink, -} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; + import type { SavedObjectConflictMessageProps } from '../types'; export const SavedObjectConflictMessage = ({ json }: SavedObjectConflictMessageProps) => { @@ -56,4 +53,4 @@ export const SavedObjectConflictMessage = ({ json }: SavedObjectConflictMessageP )} ); -}; \ No newline at end of file +}; diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts b/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts index 93b9c425441ba..465fd179c8441 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/index.ts @@ -5,7 +5,11 @@ * 2.0. */ -export { getShareToSpaceFlyoutComponent, getLegacyUrlConflict, getSavedObjectConflictMessage } from './components'; +export { + getShareToSpaceFlyoutComponent, + getLegacyUrlConflict, + getSavedObjectConflictMessage, +} from './components'; export { createRedirectLegacyUrl } from './utils'; export type { LegacyUrlConflictProps, diff --git a/x-pack/plugins/spaces/public/ui_api/types.ts b/x-pack/plugins/spaces/public/ui_api/types.ts index 7a845e8d4f09a..67e43f0cd31a6 100644 --- a/x-pack/plugins/spaces/public/ui_api/types.ts +++ b/x-pack/plugins/spaces/public/ui_api/types.ts @@ -12,8 +12,8 @@ import type { CoreStart } from 'src/core/public'; import type { CopyToSpaceFlyoutProps } from '../copy_saved_objects_to_space'; import type { LegacyUrlConflictProps, - ShareToSpaceFlyoutProps, SavedObjectConflictMessageProps, + ShareToSpaceFlyoutProps, } from '../share_saved_objects_to_space'; import type { SpaceAvatarProps } from '../space_avatar'; import type { SpaceListProps } from '../space_list'; From 49f9f31ca9a4babeb61657890e1075a14708618f Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 5 Oct 2021 07:49:50 -0600 Subject: [PATCH 8/8] review feedback --- .../maps/public/routes/map_page/map_app/map_app.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx index 0fa0de114f57d..8fc2d97c4862a 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx @@ -16,7 +16,6 @@ import type { Query, Filter, TimeRange, IndexPattern } from 'src/plugins/data/co import { getData, getCoreChrome, - getHttp, getMapsCapabilities, getNavigation, getSpacesApi, @@ -356,9 +355,7 @@ export class MapApp extends React.Component { if (spaces && sharingSavedObjectProps?.outcome === 'aliasMatch') { // We found this object by a legacy URL alias from its old ID; redirect the user to the page with its new ID, preserving any URL hash const newObjectId = sharingSavedObjectProps?.aliasTargetId; // This is always defined if outcome === 'aliasMatch' - const newPath = getHttp().basePath.prepend( - `${getFullPath(newObjectId)}${this.props.history.location.search}` - ); + const newPath = `${getEditPath(newObjectId)}${this.props.history.location.hash}`; await spaces.ui.redirectLegacyUrl(newPath, getMapEmbeddableDisplayName()); return; } @@ -456,12 +453,14 @@ export class MapApp extends React.Component { _renderLegacyUrlConflict() { const sharingSavedObjectProps = this.props.savedMap.getSharingSavedObjectProps(); const spaces = getSpacesApi(); - return sharingSavedObjectProps && spaces && sharingSavedObjectProps?.outcome === 'conflict' + return spaces && sharingSavedObjectProps?.outcome === 'conflict' ? spaces.ui.components.getLegacyUrlConflict({ objectNoun: getMapEmbeddableDisplayName(), currentObjectId: this.props.savedMap.getSavedObjectId()!, otherObjectId: sharingSavedObjectProps.aliasTargetId!, - otherObjectPath: getEditPath(sharingSavedObjectProps.aliasTargetId!), + otherObjectPath: `${getEditPath(sharingSavedObjectProps.aliasTargetId!)}${ + this.props.history.location.hash + }`, }) : null; }