Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions x-pack/plugins/lens/public/embeddable/embeddable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -41,11 +42,7 @@ import {
ReferenceOrValueEmbeddable,
} from '../../../../../src/plugins/embeddable/public';
import { Document, injectFilterReferences } from '../persistence';
import {
ExpressionWrapper,
ExpressionWrapperProps,
savedObjectConflictError,
} from './expression_wrapper';
import { ExpressionWrapper, ExpressionWrapperProps } from './expression_wrapper';
import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public';
import {
isLensBrushEvent,
Expand All @@ -63,6 +60,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<Document, 'savedObjectId' | 'type'>;
export interface ResolvedLensSavedObjectAttributes extends LensSavedObjectAttributes {
Expand Down Expand Up @@ -108,6 +106,7 @@ export interface LensEmbeddableDeps {
getTriggerCompatibleActions?: UiActionsStart['getTriggerCompatibleActions'];
capabilities: { canSaveVisualizations: boolean; canSaveDashboards: boolean };
usageCollection?: UsageCollectionSetup;
spaces?: SpacesPluginStart;
}

export class Embeddable
Expand Down Expand Up @@ -281,8 +280,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.deps.spaces.ui.components.getSavedObjectConflictMessage
json={sharingSavedObjectProps.errorJSON!}
/>
),
};
this.errors = this.errors ? [...this.errors, conflictError] : [conflictError];
}
this.expression = ast ? toExpression(ast) : null;
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/lens/public/embeddable/embeddable_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -38,6 +39,7 @@ export interface LensEmbeddableStartServices {
documentToExpression: (
doc: Document
) => Promise<{ ast: Ast | null; errors: ErrorMessage[] | undefined }>;
spaces?: SpacesPluginStart;
}

export class EmbeddableFactory implements EmbeddableFactoryDefinition {
Expand Down Expand Up @@ -90,6 +92,7 @@ export class EmbeddableFactory implements EmbeddableFactoryDefinition {
capabilities,
usageCollection,
inspector,
spaces,
} = await this.getStartServices();

const { Embeddable } = await import('../async_services');
Expand All @@ -110,6 +113,7 @@ export class EmbeddableFactory implements EmbeddableFactoryDefinition {
canSaveVisualizations: Boolean(capabilities.visualize.save),
},
usageCollection,
spaces,
},
input,
parent
Expand Down
64 changes: 2 additions & 62 deletions x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,10 @@
* 2.0.
*/

import React, { useState } from 'react';
import React from 'react';
import { I18nProvider } from '@kbn/i18n/react';
import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiFlexGroup,
EuiFlexItem,
EuiText,
EuiIcon,
EuiEmptyPrompt,
EuiButtonEmpty,
EuiCallOut,
EuiSpacer,
EuiLink,
} from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiText, EuiIcon, EuiEmptyPrompt } from '@elastic/eui';
import {
ExpressionRendererEvent,
ReactExpressionRendererType,
Expand All @@ -28,7 +18,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';
Expand Down Expand Up @@ -172,52 +161,3 @@ export function ExpressionWrapper({
</I18nProvider>
);
}

const SavedObjectConflictMessage = ({ json }: { json: string }) => {
const [expandError, setExpandError] = useState(false);
return (
<>
<FormattedMessage
id="xpack.lens.embeddable.legacyURLConflict.longMessage"
defaultMessage="Disable the {documentationLink} associated with this object."
values={{
documentationLink: (
<EuiLink
external
href="https://www.elastic.co/guide/en/kibana/master/legacy-url-aliases.html"
target="_blank"
>
{i18n.translate('xpack.lens.embeddable.legacyURLConflict.documentationLinkText', {
defaultMessage: 'legacy URL alias',
})}
</EuiLink>
),
}}
/>
<EuiSpacer />
{expandError ? (
<EuiCallOut
title={i18n.translate('xpack.lens.embeddable.legacyURLConflict.expandErrorText', {
defaultMessage: `This object has the same URL as a legacy alias. Disable the alias to resolve this error : {json}`,
values: { json },
})}
color="danger"
iconType="alert"
/>
) : (
<EuiButtonEmpty onClick={() => setExpandError(true)}>
{i18n.translate('xpack.lens.embeddable.legacyURLConflict.expandError', {
defaultMessage: `Show more`,
})}
</EuiButtonEmpty>
)}
</>
);
};

export const savedObjectConflictError = (json: string): ErrorMessage => ({
shortMessage: i18n.translate('xpack.lens.embeddable.legacyURLConflict.shortMessage', {
defaultMessage: `You've encountered a URL conflict`,
}),
longMessage: <SavedObjectConflictMessage json={json} />,
});
1 change: 1 addition & 0 deletions x-pack/plugins/lens/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ export class LensPlugin {
uiActions: plugins.uiActions,
usageCollection,
inspector: plugins.inspector,
spaces: plugins.spaces,
};
};

Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/maps/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"savedObjectsTagging",
"charts",
"security",
"spaces",
"usageCollection"
],
"ui": true,
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/maps/public/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
@import 'connected_components/index';
@import 'components/index';
@import 'classes/index';
@import 'animations';
@import 'animations';
@import 'embeddable/index';
7 changes: 7 additions & 0 deletions x-pack/plugins/maps/public/embeddable/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.mapEmbeddedError {
flex-grow: 1;
display: flex;
align-items: center;
justify-content: center;
overflow: auto;
}
43 changes: 30 additions & 13 deletions x-pack/plugins/maps/public/embeddable/map_embeddable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -65,6 +66,7 @@ import {
getCoreI18n,
getHttp,
getChartsPaletteServiceGetColor,
getSpacesApi,
getSearchService,
} from '../kibana_services';
import { LayerDescriptor, MapExtent } from '../../common/descriptor_types';
Expand Down Expand Up @@ -338,22 +340,37 @@ export class MapEmbeddable
return;
}

const I18nContext = getCoreI18n().Context;
const sharingSavedObjectProps = this._savedMap.getSharingSavedObjectProps();
const spaces = getSpacesApi();
const content =
sharingSavedObjectProps && spaces && sharingSavedObjectProps?.outcome === 'conflict' ? (
<div className="mapEmbeddedError">
<EuiEmptyPrompt
iconType="alert"
iconColor="danger"
data-test-subj="embeddable-maps-failure"
body={spaces.ui.components.getSavedObjectConflictMessage({
json: sharingSavedObjectProps.errorJSON!,
})}
/>
</div>
) : (
<MapContainer
onSingleValueTrigger={this.onSingleValueTrigger}
addFilters={this.input.hideFilterActions ? null : this.addFilters}
getFilterActions={this.getFilterActions}
getActionContext={this.getActionContext}
renderTooltipContent={this._renderTooltipContent}
title={this.getTitle()}
description={this.getDescription()}
waitUntilTimeLayersLoad$={waitUntilTimeLayersLoad$(this._savedMap.getStore())}
/>
);

const I18nContext = getCoreI18n().Context;
render(
<Provider store={this._savedMap.getStore()}>
<I18nContext>
<MapContainer
onSingleValueTrigger={this.onSingleValueTrigger}
addFilters={this.input.hideFilterActions ? null : this.addFilters}
getFilterActions={this.getFilterActions}
getActionContext={this.getActionContext}
renderTooltipContent={this._renderTooltipContent}
title={this.getTitle()}
description={this.getDescription()}
waitUntilTimeLayersLoad$={waitUntilTimeLayersLoad$(this._savedMap.getStore())}
/>
</I18nContext>
<I18nContext>{content}</I18nContext>
</Provider>,
this._domNode
);
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/maps/public/kibana_services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
35 changes: 32 additions & 3 deletions x-pack/plugins/maps/public/map_attribute_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[] };
export interface SharingSavedObjectProps {
outcome?: 'aliasMatch' | 'exactMatch' | 'conflict';
aliasTargetId?: string;
errorJSON?: string;
}

type MapDoc = MapSavedObjectAttributes & {
sharingSavedObjectProps?: SharingSavedObjectProps;
references?: SavedObjectReference[];
};

export type MapAttributeService = AttributeService<MapDoc, MapByValueInput, MapByReferenceInput>;

Expand Down Expand Up @@ -58,7 +68,11 @@ export function getMapAttributeService(): MapAttributeService {
return { id: savedObject.id };
},
unwrapMethod: async (savedObjectId: string): Promise<MapDoc> => {
const savedObject = await getSavedObjectsClient().get<MapSavedObjectAttributes>(
const {
saved_object: savedObject,
outcome,
alias_target_id: aliasTargetId,
} = await getSavedObjectsClient().resolve<MapSavedObjectAttributes>(
MAP_SAVED_OBJECT_TYPE,
savedObjectId
);
Expand All @@ -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(
Expand Down
4 changes: 3 additions & 1 deletion x-pack/plugins/maps/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ import {
MapsAppRegionMapLocatorDefinition,
MapsAppTileMapLocatorDefinition,
} from './locators';
import { SecurityPluginStart } from '../../security/public';
import type { SecurityPluginStart } from '../../security/public';
import type { SpacesPluginStart } from '../../spaces/public';

export interface MapsPluginSetupDependencies {
inspector: InspectorSetupContract;
Expand Down Expand Up @@ -103,6 +104,7 @@ export interface MapsPluginStartDependencies {
savedObjectsTagging?: SavedObjectTaggingPluginStart;
presentationUtil: PresentationUtilPluginStart;
security: SecurityPluginStart;
spaces?: SpacesPluginStart;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/maps/public/render_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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'}
/>
);
Expand Down
Loading