Skip to content

Commit

Permalink
[Graph] Save modal (#44261) (#44918)
Browse files Browse the repository at this point in the history
  • Loading branch information
flash1293 authored Sep 6, 2019
1 parent e97c1a6 commit cffc08a
Show file tree
Hide file tree
Showing 18 changed files with 298 additions and 177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter';

import { docTitle } from 'ui/doc_title/doc_title';

// @ts-ignore
import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal';
import { showSaveModal, SaveResult } from 'ui/saved_objects/show_saved_object_save_modal';

import { showShareContextMenu, ShareContextMenuExtensionsRegistryProvider } from 'ui/share';
import { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query';
Expand Down Expand Up @@ -604,7 +603,7 @@ export class DashboardAppController {
* @return {Promise}
* @resolved {String} - The id of the doc
*/
function save(saveOptions: SaveOptions): Promise<{ id?: string } | { error: Error }> {
function save(saveOptions: SaveOptions): Promise<SaveResult> {
return saveDashboard(angular.toJson, timefilter, dashboardStateManager, saveOptions)
.then(function(id) {
if (id) {
Expand Down Expand Up @@ -695,7 +694,7 @@ export class DashboardAppController {
isTitleDuplicateConfirmed,
onTitleDuplicate,
};
return save(saveOptions).then((response: { id?: string } | { error: Error }) => {
return save(saveOptions).then((response: SaveResult) => {
// If the save wasn't successful, put the original values back.
if (!(response as { id: string }).id) {
dashboardStateManager.setTitle(currentTitle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ import 'uiExports/visualize';
import { i18n } from '@kbn/i18n';

import { capabilities } from 'ui/capabilities';
// @ts-ignore
import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal';
// @ts-ignore
import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';

import chrome from 'ui/chrome';
import { getVisualizeLoader } from 'ui/visualize/loader';
Expand Down
1 change: 1 addition & 0 deletions src/legacy/ui/public/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
@import './exit_full_screen/index';
@import './field_editor/index';
@import './notify/index';
@import './saved_objects/index';
@import './share/index';
@import './style_compile/index';

Expand Down
1 change: 1 addition & 0 deletions src/legacy/ui/public/saved_objects/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import '../../../../plugins/kibana_react/public/saved_objects/index';
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,25 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { I18nContext } from 'ui/i18n';

export function showSaveModal(saveModal) {
/**
* Represents the result of trying to persist the saved object.
* Contains `error` prop if something unexpected happened (e.g. network error).
* Contains an `id` if persisting was successful. If `id` and
* `error` are undefined, persisting was not successful, but the
* modal can still recover (e.g. the name of the saved object was already taken).
*/
export type SaveResult = { id?: string } | { error: Error };

function isSuccess(result: SaveResult): result is { id?: string } {
return 'id' in result;
}

interface MinimalSaveModalProps {
onSave: (...args: any[]) => Promise<SaveResult>;
onClose: () => void;
}

export function showSaveModal(saveModal: React.ReactElement<MinimalSaveModalProps>) {
const container = document.createElement('div');
const closeModal = () => {
ReactDOM.unmountComponentAtNode(container);
Expand All @@ -30,21 +48,19 @@ export function showSaveModal(saveModal) {

const onSave = saveModal.props.onSave;

const onSaveConfirmed = (...args) => {
onSave(...args).then(({ id, error }) => {
if (id || error) {
closeModal();
}
});
const onSaveConfirmed: MinimalSaveModalProps['onSave'] = async (...args) => {
const response = await onSave(...args);
// close modal if we either hit an error or the saved object got an id
if (Boolean(isSuccess(response) ? response.id : response.error)) {
closeModal();
}
return response;
};
document.body.appendChild(container);
const element = React.cloneElement(
saveModal,
{
onSave: onSaveConfirmed,
onClose: closeModal
}
);
const element = React.cloneElement(saveModal, {
onSave: onSaveConfirmed,
onClose: closeModal,
});

ReactDOM.render(<I18nContext>{element}</I18nContext>, container);
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/plugins/kibana_react/public/saved_objects/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import './saved_object_save_modal';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.kbnSavedObjectSaveModal {
width: $euiSizeXXL * 10;
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ import {
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
import { EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

interface OnSaveProps {
export interface OnSaveProps {
newTitle: string;
newCopyOnSave: boolean;
isTitleDuplicateConfirmed: boolean;
Expand Down Expand Up @@ -72,14 +73,14 @@ export class SavedObjectSaveModal extends React.Component<Props, State> {
};

public render() {
const { isTitleDuplicateConfirmed, hasTitleDuplicate, title, isLoading } = this.state;
const { isTitleDuplicateConfirmed, hasTitleDuplicate, title } = this.state;

return (
<EuiOverlayMask>
<form onSubmit={this.onFormSubmit}>
<EuiModal
data-test-subj="savedObjectSaveModal"
className="dshSaveModal"
className="kbnSavedObjectSaveModal"
onClose={this.props.onClose}
>
<EuiModalHeader>
Expand Down Expand Up @@ -136,22 +137,7 @@ export class SavedObjectSaveModal extends React.Component<Props, State> {
/>
</EuiButtonEmpty>

<EuiButton
fill
data-test-subj="confirmSaveSavedObjectButton"
isLoading={isLoading}
isDisabled={title.length === 0}
type="submit"
>
{this.props.confirmButtonLabel ? (
this.props.confirmButtonLabel
) : (
<FormattedMessage
id="kibana-react.savedObjects.saveModal.confirmSaveButtonLabel"
defaultMessage="Confirm Save"
/>
)}
</EuiButton>
{this.renderConfirmButton()}
</EuiModalFooter>
</EuiModal>
</form>
Expand Down Expand Up @@ -204,6 +190,34 @@ export class SavedObjectSaveModal extends React.Component<Props, State> {
this.saveSavedObject();
};

private renderConfirmButton = () => {
const { isLoading, title, hasTitleDuplicate } = this.state;

let confirmLabel: string | React.ReactNode = hasTitleDuplicate
? i18n.translate('kibana-react.savedObjects.saveModal.confirmSaveButtonLabel', {
defaultMessage: 'Confirm save',
})
: i18n.translate('kibana-react.savedObjects.saveModal.saveButtonLabel', {
defaultMessage: 'Save',
});

if (this.props.confirmButtonLabel) {
confirmLabel = this.props.confirmButtonLabel;
}

return (
<EuiButton
fill
data-test-subj="confirmSaveSavedObjectButton"
isLoading={isLoading}
isDisabled={title.length === 0}
type="submit"
>
{confirmLabel}
</EuiButton>
);
};

private renderDuplicateTitleCallout = () => {
if (!this.state.hasTitleDuplicate) {
return;
Expand All @@ -230,10 +244,14 @@ export class SavedObjectSaveModal extends React.Component<Props, State> {
objectType: this.props.objectType,
confirmSaveLabel: (
<strong>
<FormattedMessage
id="kibana-react.savedObjects.saveModal.duplicateTitleDescription.confirmSaveText"
defaultMessage="Confirm Save"
/>
{this.props.confirmButtonLabel
? this.props.confirmButtonLabel
: i18n.translate(
'kibana-react.savedObjects.saveModal.duplicateTitleDescription.confirmSaveText',
{
defaultMessage: 'Confirm save',
}
)}
</strong>
),
}}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
<kbn-top-nav name="workspacesTopNav" config="topNavMenu">
</kbn-top-nav>

<div class="gphGraph__menus" ng-show="menus.showSave || menus.showSettings">
<graph-save ng-show="menus.showSave"></graph-save>
<div class="gphGraph__menus" ng-show="menus.showSettings">
<graph-settings ng-show="menus.showSettings"></graph-settings>
</div>

Expand Down

This file was deleted.

Loading

0 comments on commit cffc08a

Please sign in to comment.