Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lens] Expose save dialog behavior via plugin contract #94585

Closed
flash1293 opened this issue Mar 15, 2021 · 1 comment · Fixed by #100381
Closed

[Lens] Expose save dialog behavior via plugin contract #94585

flash1293 opened this issue Mar 15, 2021 · 1 comment · Fixed by #100381
Assignees
Labels
enhancement New value added to drive a business result Feature:Lens Team:Visualizations Visualization editors, elastic-charts and infrastructure

Comments

@flash1293
Copy link
Contributor

flash1293 commented Mar 15, 2021

It's possible to create a Lens saved object (or drop the user in a dashboard with it) without intervention from the Lens plugin, but as there's quite some boilerplate code required it would make sense to expose it similar to the method linking to a pre-filled editor.

It's mostly about exposing this functionality:

const originalInput = saveProps.newCopyOnSave ? undefined : initialInput;
const originalSavedObjectId = (originalInput as LensByReferenceInput)?.savedObjectId;
if (options.saveToLibrary) {
try {
await checkForDuplicateTitle(
{
id: originalSavedObjectId,
title: docToSave.title,
copyOnSave: saveProps.newCopyOnSave,
lastSavedTitle: lastKnownDoc.title,
getEsType: () => 'lens',
getDisplayName: () =>
i18n.translate('xpack.lens.app.saveModalType', {
defaultMessage: 'Lens visualization',
}),
},
saveProps.isTitleDuplicateConfirmed,
saveProps.onTitleDuplicate,
{
savedObjectsClient,
overlays,
}
);
} catch (e) {
// ignore duplicate title failure, user notified in save modal
return;
}
}
try {
const newInput = (await attributeService.wrapAttributes(
docToSave,
options.saveToLibrary,
originalInput
)) as LensEmbeddableInput;
if (saveProps.returnToOrigin && redirectToOrigin) {
// disabling the validation on app leave because the document has been saved.
onAppLeave((actions) => {
return actions.default();
});
redirectToOrigin({ input: newInput, isCopied: saveProps.newCopyOnSave });
return;
} else if (saveProps.dashboardId && redirectToDashboard) {
// disabling the validation on app leave because the document has been saved.
onAppLeave((actions) => {
return actions.default();
});
redirectToDashboard(newInput, saveProps.dashboardId);
return;
}
notifications.toasts.addSuccess(
i18n.translate('xpack.lens.app.saveVisualization.successNotificationText', {
defaultMessage: `Saved '{visTitle}'`,
values: {
visTitle: docToSave.title,
},
})
);
if (
attributeService.inputIsRefType(newInput) &&
newInput.savedObjectId !== originalSavedObjectId
) {
chrome.recentlyAccessed.add(
getFullPath(newInput.savedObjectId),
docToSave.title,
newInput.savedObjectId
);
setState((s) => ({
...s,
isSaveModalVisible: false,
isLinkedToOriginatingApp: false,
}));
// remove editor state so the connection is still broken after reload
stateTransfer.clearEditorState(APP_ID);
redirectTo(newInput.savedObjectId);
return;
}

export const SaveModal = (props: Props) => {
if (!props.isVisible || !props.lastKnownDoc) {
return null;
}
const {
originatingApp,
savedObjectsTagging,
tagsIds,
lastKnownDoc,
allowByValueEmbeddables,
returnToOriginSwitchLabel,
getAppNameFromId,
onClose,
onSave,
} = props;
// Use the modal with return-to-origin features if we're in an app's edit flow or if by-value embeddables are disabled
if (originatingApp || !allowByValueEmbeddables) {
return (
<TagEnhancedSavedObjectSaveModalOrigin
savedObjectsTagging={savedObjectsTagging}
initialTags={tagsIds}
originatingApp={originatingApp}
onClose={onClose}
onSave={(saveProps) => onSave(saveProps, { saveToLibrary: true })}
getAppNameFromId={getAppNameFromId}
documentInfo={{
id: lastKnownDoc.savedObjectId,
title: lastKnownDoc.title || '',
description: lastKnownDoc.description || '',
}}
returnToOriginSwitchLabel={returnToOriginSwitchLabel}
objectType={i18n.translate('xpack.lens.app.saveModalType', {
defaultMessage: 'Lens visualization',
})}
data-test-subj="lnsApp_saveModalOrigin"
/>
);
}
return (
<TagEnhancedSavedObjectSaveModalDashboard
savedObjectsTagging={savedObjectsTagging}
initialTags={tagsIds}
onSave={(saveProps) => {
const saveToLibrary = saveProps.dashboardId === null;
onSave(saveProps, { saveToLibrary });
}}
onClose={onClose}
documentInfo={{
id: lastKnownDoc.savedObjectId,
title: lastKnownDoc.title || '',
description: lastKnownDoc.description || '',
}}
objectType={i18n.translate('xpack.lens.app.saveModalType', {
defaultMessage: 'Lens visualization',
})}
data-test-subj="lnsApp_saveModalDashboard"
/>
);

The UI could look like this:

openLensSaveModal: (input: LensEmbeddableInput) => Promise<{ aborted: true } | { aborted: false; savedTo: 'dashboard' | 'savedObject'; id: string }>
@flash1293 flash1293 added enhancement New value added to drive a business result Team:Visualizations Visualization editors, elastic-charts and infrastructure Feature:Lens labels Mar 15, 2021
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-app (Team:KibanaApp)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New value added to drive a business result Feature:Lens Team:Visualizations Visualization editors, elastic-charts and infrastructure
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants