mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[CANVAS] Moves notify to a canvas service (#63268)
* Moves notify to a canvas service * Typecheck fix
This commit is contained in:
parent
dfddcdd903
commit
4051c94568
24 changed files with 287 additions and 152 deletions
|
@ -33,6 +33,9 @@ import { ACTION_VALUE_CLICK } from '../../../../../src/plugins/data/public/actio
|
||||||
import { init as initStatsReporter } from './lib/ui_metric';
|
import { init as initStatsReporter } from './lib/ui_metric';
|
||||||
|
|
||||||
import { CapabilitiesStrings } from '../i18n';
|
import { CapabilitiesStrings } from '../i18n';
|
||||||
|
|
||||||
|
import { startServices, stopServices, services } from './services';
|
||||||
|
|
||||||
const { ReadOnlyBadge: strings } = CapabilitiesStrings;
|
const { ReadOnlyBadge: strings } = CapabilitiesStrings;
|
||||||
|
|
||||||
let restoreAction: ActionByType<any> | undefined;
|
let restoreAction: ActionByType<any> | undefined;
|
||||||
|
@ -51,8 +54,14 @@ export const renderApp = (
|
||||||
{ element }: AppMountParameters,
|
{ element }: AppMountParameters,
|
||||||
canvasStore: Store
|
canvasStore: Store
|
||||||
) => {
|
) => {
|
||||||
|
const canvasServices = Object.entries(services).reduce((reduction, [key, provider]) => {
|
||||||
|
reduction[key] = provider.getService();
|
||||||
|
|
||||||
|
return reduction;
|
||||||
|
}, {} as Record<string, any>);
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<KibanaContextProvider services={{ ...plugins, ...coreStart }}>
|
<KibanaContextProvider services={{ ...plugins, ...coreStart, canvas: canvasServices }}>
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<Provider store={canvasStore}>
|
<Provider store={canvasStore}>
|
||||||
<App />
|
<App />
|
||||||
|
@ -71,6 +80,8 @@ export const initializeCanvas = async (
|
||||||
startPlugins: CanvasStartDeps,
|
startPlugins: CanvasStartDeps,
|
||||||
registries: SetupRegistries
|
registries: SetupRegistries
|
||||||
) => {
|
) => {
|
||||||
|
startServices(coreSetup, coreStart, setupPlugins, startPlugins);
|
||||||
|
|
||||||
// Create Store
|
// Create Store
|
||||||
const canvasStore = await createStore(coreSetup, setupPlugins);
|
const canvasStore = await createStore(coreSetup, setupPlugins);
|
||||||
|
|
||||||
|
@ -130,6 +141,7 @@ export const initializeCanvas = async (
|
||||||
};
|
};
|
||||||
|
|
||||||
export const teardownCanvas = (coreStart: CoreStart, startPlugins: CanvasStartDeps) => {
|
export const teardownCanvas = (coreStart: CoreStart, startPlugins: CanvasStartDeps) => {
|
||||||
|
stopServices();
|
||||||
destroyRegistries();
|
destroyRegistries();
|
||||||
resetInterpreter();
|
resetInterpreter();
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
import { ErrorStrings } from '../../../i18n';
|
import { ErrorStrings } from '../../../i18n';
|
||||||
import * as workpadService from '../../lib/workpad_service';
|
import * as workpadService from '../../lib/workpad_service';
|
||||||
import { notify } from '../../lib/notify';
|
import { notifyService } from '../../services';
|
||||||
import { getBaseBreadcrumb, getWorkpadBreadcrumb, setBreadcrumb } from '../../lib/breadcrumbs';
|
import { getBaseBreadcrumb, getWorkpadBreadcrumb, setBreadcrumb } from '../../lib/breadcrumbs';
|
||||||
import { getDefaultWorkpad } from '../../state/defaults';
|
import { getDefaultWorkpad } from '../../state/defaults';
|
||||||
import { setWorkpad } from '../../state/actions/workpad';
|
import { setWorkpad } from '../../state/actions/workpad';
|
||||||
|
@ -33,7 +33,9 @@ export const routes = [
|
||||||
dispatch(resetAssets());
|
dispatch(resetAssets());
|
||||||
router.redirectTo('loadWorkpad', { id: newWorkpad.id, page: 1 });
|
router.redirectTo('loadWorkpad', { id: newWorkpad.id, page: 1 });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: strings.getCreateFailureErrorMessage() });
|
notifyService
|
||||||
|
.getService()
|
||||||
|
.error(err, { title: strings.getCreateFailureErrorMessage() });
|
||||||
router.redirectTo('home');
|
router.redirectTo('home');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -59,7 +61,9 @@ export const routes = [
|
||||||
// reset transient properties when changing workpads
|
// reset transient properties when changing workpads
|
||||||
dispatch(setZoomScale(1));
|
dispatch(setZoomScale(1));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: strings.getLoadFailureErrorMessage() });
|
notifyService
|
||||||
|
.getService()
|
||||||
|
.error(err, { title: strings.getLoadFailureErrorMessage() });
|
||||||
return router.redirectTo('home');
|
return router.redirectTo('home');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { AssetModal } from './asset_modal';
|
||||||
|
|
||||||
const { AssetManager: strings } = ComponentStrings;
|
const { AssetManager: strings } = ComponentStrings;
|
||||||
|
|
||||||
interface Props {
|
export interface Props {
|
||||||
/** A list of assets, if available */
|
/** A list of assets, if available */
|
||||||
assetValues: AssetType[];
|
assetValues: AssetType[];
|
||||||
/** Function to invoke when an asset is selected to be added as an element to the workpad */
|
/** Function to invoke when an asset is selected to be added as an element to the workpad */
|
||||||
|
|
|
@ -8,29 +8,36 @@ import { connect } from 'react-redux';
|
||||||
import { compose, withProps } from 'recompose';
|
import { compose, withProps } from 'recompose';
|
||||||
import { set, get } from 'lodash';
|
import { set, get } from 'lodash';
|
||||||
import { fromExpression, toExpression } from '@kbn/interpreter/common';
|
import { fromExpression, toExpression } from '@kbn/interpreter/common';
|
||||||
import { notify } from '../../lib/notify';
|
|
||||||
import { getAssets } from '../../state/selectors/assets';
|
import { getAssets } from '../../state/selectors/assets';
|
||||||
|
// @ts-ignore Untyped local
|
||||||
import { removeAsset, createAsset } from '../../state/actions/assets';
|
import { removeAsset, createAsset } from '../../state/actions/assets';
|
||||||
|
// @ts-ignore Untyped local
|
||||||
import { elementsRegistry } from '../../lib/elements_registry';
|
import { elementsRegistry } from '../../lib/elements_registry';
|
||||||
|
// @ts-ignore Untyped local
|
||||||
import { addElement } from '../../state/actions/elements';
|
import { addElement } from '../../state/actions/elements';
|
||||||
import { getSelectedPage } from '../../state/selectors/workpad';
|
import { getSelectedPage } from '../../state/selectors/workpad';
|
||||||
import { encode } from '../../../common/lib/dataurl';
|
import { encode } from '../../../common/lib/dataurl';
|
||||||
import { getId } from '../../lib/get_id';
|
import { getId } from '../../lib/get_id';
|
||||||
|
// @ts-ignore Untyped Local
|
||||||
import { findExistingAsset } from '../../lib/find_existing_asset';
|
import { findExistingAsset } from '../../lib/find_existing_asset';
|
||||||
import { VALID_IMAGE_TYPES } from '../../../common/lib/constants';
|
import { VALID_IMAGE_TYPES } from '../../../common/lib/constants';
|
||||||
import { AssetManager as Component } from './asset_manager';
|
import { withKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||||
|
import { WithKibanaProps } from '../../';
|
||||||
|
import { AssetManager as Component, Props as AssetManagerProps } from './asset_manager';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
import { State, ExpressionAstExpression, AssetType } from '../../../types';
|
||||||
|
|
||||||
|
const mapStateToProps = (state: State) => ({
|
||||||
assets: getAssets(state),
|
assets: getAssets(state),
|
||||||
selectedPage: getSelectedPage(state),
|
selectedPage: getSelectedPage(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = (dispatch: (action: any) => void) => ({
|
||||||
onAddImageElement: pageId => assetId => {
|
onAddImageElement: (pageId: string) => (assetId: string) => {
|
||||||
const imageElement = elementsRegistry.get('image');
|
const imageElement = elementsRegistry.get('image');
|
||||||
const elementAST = fromExpression(imageElement.expression);
|
const elementAST = fromExpression(imageElement.expression);
|
||||||
const selector = ['chain', '0', 'arguments', 'dataurl'];
|
const selector = ['chain', '0', 'arguments', 'dataurl'];
|
||||||
const subExp = [
|
const subExp: ExpressionAstExpression[] = [
|
||||||
{
|
{
|
||||||
type: 'expression',
|
type: 'expression',
|
||||||
chain: [
|
chain: [
|
||||||
|
@ -44,11 +51,11 @@ const mapDispatchToProps = dispatch => ({
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const newAST = set(elementAST, selector, subExp);
|
const newAST = set<ExpressionAstExpression>(elementAST, selector, subExp);
|
||||||
imageElement.expression = toExpression(newAST);
|
imageElement.expression = toExpression(newAST);
|
||||||
dispatch(addElement(pageId, imageElement));
|
dispatch(addElement(pageId, imageElement));
|
||||||
},
|
},
|
||||||
onAssetAdd: (type, content) => {
|
onAssetAdd: (type: string, content: string) => {
|
||||||
// make the ID here and pass it into the action
|
// make the ID here and pass it into the action
|
||||||
const assetId = getId('asset');
|
const assetId = getId('asset');
|
||||||
dispatch(createAsset(type, content, assetId));
|
dispatch(createAsset(type, content, assetId));
|
||||||
|
@ -56,10 +63,14 @@ const mapDispatchToProps = dispatch => ({
|
||||||
// then return the id, so the caller knows the id that will be created
|
// then return the id, so the caller knows the id that will be created
|
||||||
return assetId;
|
return assetId;
|
||||||
},
|
},
|
||||||
onAssetDelete: assetId => dispatch(removeAsset(assetId)),
|
onAssetDelete: (assetId: string) => dispatch(removeAsset(assetId)),
|
||||||
});
|
});
|
||||||
|
|
||||||
const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
const mergeProps = (
|
||||||
|
stateProps: ReturnType<typeof mapStateToProps>,
|
||||||
|
dispatchProps: ReturnType<typeof mapDispatchToProps>,
|
||||||
|
ownProps: AssetManagerProps
|
||||||
|
) => {
|
||||||
const { assets, selectedPage } = stateProps;
|
const { assets, selectedPage } = stateProps;
|
||||||
const { onAssetAdd } = dispatchProps;
|
const { onAssetAdd } = dispatchProps;
|
||||||
const assetValues = Object.values(assets); // pull values out of assets object
|
const assetValues = Object.values(assets); // pull values out of assets object
|
||||||
|
@ -70,16 +81,16 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||||
onAddImageElement: dispatchProps.onAddImageElement(stateProps.selectedPage),
|
onAddImageElement: dispatchProps.onAddImageElement(stateProps.selectedPage),
|
||||||
selectedPage,
|
selectedPage,
|
||||||
assetValues,
|
assetValues,
|
||||||
onAssetAdd: file => {
|
onAssetAdd: (file: File) => {
|
||||||
const [type, subtype] = get(file, 'type', '').split('/');
|
const [type, subtype] = get(file, 'type', '').split('/');
|
||||||
if (type === 'image' && VALID_IMAGE_TYPES.indexOf(subtype) >= 0) {
|
if (type === 'image' && VALID_IMAGE_TYPES.indexOf(subtype) >= 0) {
|
||||||
return encode(file).then(dataurl => {
|
return encode(file).then(dataurl => {
|
||||||
const type = 'dataurl';
|
const dataurlType = 'dataurl';
|
||||||
const existingId = findExistingAsset(type, dataurl, assetValues);
|
const existingId = findExistingAsset(dataurlType, dataurl, assetValues);
|
||||||
if (existingId) {
|
if (existingId) {
|
||||||
return existingId;
|
return existingId;
|
||||||
}
|
}
|
||||||
return onAssetAdd(type, dataurl);
|
return onAssetAdd(dataurlType, dataurl);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +99,11 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AssetManager = compose(
|
export const AssetManager = compose<any, any>(
|
||||||
connect(mapStateToProps, mapDispatchToProps, mergeProps),
|
connect(mapStateToProps, mapDispatchToProps, mergeProps),
|
||||||
withProps({ onAssetCopy: asset => notify.success(`Copied '${asset.id}' to clipboard`) })
|
withKibana,
|
||||||
|
withProps(({ kibana }: WithKibanaProps) => ({
|
||||||
|
onAssetCopy: (asset: AssetType) =>
|
||||||
|
kibana.services.canvas.notify.success(`Copied '${asset.id}' to clipboard`),
|
||||||
|
}))
|
||||||
)(Component);
|
)(Component);
|
|
@ -7,7 +7,7 @@
|
||||||
import { compose, withProps, withPropsOnChange } from 'recompose';
|
import { compose, withProps, withPropsOnChange } from 'recompose';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import isEqual from 'react-fast-compare';
|
import isEqual from 'react-fast-compare';
|
||||||
import { notify } from '../../lib/notify';
|
import { withKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||||
import { RenderWithFn as Component } from './render_with_fn';
|
import { RenderWithFn as Component } from './render_with_fn';
|
||||||
import { ElementHandlers } from './lib/handlers';
|
import { ElementHandlers } from './lib/handlers';
|
||||||
|
|
||||||
|
@ -19,9 +19,10 @@ export const RenderWithFn = compose(
|
||||||
handlers: Object.assign(new ElementHandlers(), handlers),
|
handlers: Object.assign(new ElementHandlers(), handlers),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
withProps({
|
withKibana,
|
||||||
onError: notify.error,
|
withProps(props => ({
|
||||||
})
|
onError: props.kibana.services.canvas.notify.error,
|
||||||
|
}))
|
||||||
)(Component);
|
)(Component);
|
||||||
|
|
||||||
RenderWithFn.propTypes = {
|
RenderWithFn.propTypes = {
|
||||||
|
|
|
@ -11,8 +11,8 @@ import { camelCase } from 'lodash';
|
||||||
// @ts-ignore Untyped local
|
// @ts-ignore Untyped local
|
||||||
import { cloneSubgraphs } from '../../lib/clone_subgraphs';
|
import { cloneSubgraphs } from '../../lib/clone_subgraphs';
|
||||||
import * as customElementService from '../../lib/custom_element_service';
|
import * as customElementService from '../../lib/custom_element_service';
|
||||||
// @ts-ignore Untyped local
|
import { withKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||||
import { notify } from '../../lib/notify';
|
import { WithKibanaProps } from '../../';
|
||||||
// @ts-ignore Untyped local
|
// @ts-ignore Untyped local
|
||||||
import { selectToplevelNodes } from '../../state/actions/transient';
|
import { selectToplevelNodes } from '../../state/actions/transient';
|
||||||
// @ts-ignore Untyped local
|
// @ts-ignore Untyped local
|
||||||
|
@ -64,7 +64,7 @@ const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({
|
||||||
const mergeProps = (
|
const mergeProps = (
|
||||||
stateProps: StateProps,
|
stateProps: StateProps,
|
||||||
dispatchProps: DispatchProps,
|
dispatchProps: DispatchProps,
|
||||||
ownProps: OwnPropsWithState
|
ownProps: OwnPropsWithState & WithKibanaProps
|
||||||
): ComponentProps => {
|
): ComponentProps => {
|
||||||
const { pageId } = stateProps;
|
const { pageId } = stateProps;
|
||||||
const { onClose, search, setCustomElements } = ownProps;
|
const { onClose, search, setCustomElements } = ownProps;
|
||||||
|
@ -92,7 +92,9 @@ const mergeProps = (
|
||||||
try {
|
try {
|
||||||
await findCustomElements();
|
await findCustomElements();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: `Couldn't find custom elements` });
|
ownProps.kibana.services.canvas.notify.error(err, {
|
||||||
|
title: `Couldn't find custom elements`,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// remove custom element
|
// remove custom element
|
||||||
|
@ -101,7 +103,9 @@ const mergeProps = (
|
||||||
await customElementService.remove(id);
|
await customElementService.remove(id);
|
||||||
await findCustomElements();
|
await findCustomElements();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: `Couldn't delete custom elements` });
|
ownProps.kibana.services.canvas.notify.error(err, {
|
||||||
|
title: `Couldn't delete custom elements`,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// update custom element
|
// update custom element
|
||||||
|
@ -115,13 +119,16 @@ const mergeProps = (
|
||||||
});
|
});
|
||||||
await findCustomElements();
|
await findCustomElements();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: `Couldn't update custom elements` });
|
ownProps.kibana.services.canvas.notify.error(err, {
|
||||||
|
title: `Couldn't update custom elements`,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SavedElementsModal = compose<ComponentProps, OwnProps>(
|
export const SavedElementsModal = compose<ComponentProps, OwnProps>(
|
||||||
|
withKibana,
|
||||||
withState('search', 'setSearch', ''),
|
withState('search', 'setSearch', ''),
|
||||||
withState('customElements', 'setCustomElements', []),
|
withState('customElements', 'setCustomElements', []),
|
||||||
connect(mapStateToProps, mapDispatchToProps, mergeProps)
|
connect(mapStateToProps, mapDispatchToProps, mergeProps)
|
||||||
|
|
|
@ -12,7 +12,6 @@ import {
|
||||||
getRenderedWorkpadExpressions,
|
getRenderedWorkpadExpressions,
|
||||||
} from '../../../../state/selectors/workpad';
|
} from '../../../../state/selectors/workpad';
|
||||||
// @ts-ignore Untyped local
|
// @ts-ignore Untyped local
|
||||||
import { notify } from '../../../../lib/notify';
|
|
||||||
import {
|
import {
|
||||||
downloadRenderedWorkpad,
|
downloadRenderedWorkpad,
|
||||||
downloadRuntime,
|
downloadRuntime,
|
||||||
|
@ -70,7 +69,7 @@ export const ShareWebsiteFlyout = compose<ComponentProps, Pick<Props, 'onClose'>
|
||||||
unsupportedRenderers,
|
unsupportedRenderers,
|
||||||
onClose,
|
onClose,
|
||||||
onCopy: () => {
|
onCopy: () => {
|
||||||
notify.info(strings.getCopyShareConfigMessage());
|
kibana.services.canvas.notify.info(strings.getCopyShareConfigMessage());
|
||||||
},
|
},
|
||||||
onDownload: type => {
|
onDownload: type => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -86,7 +85,9 @@ export const ShareWebsiteFlyout = compose<ComponentProps, Pick<Props, 'onClose'>
|
||||||
.post(`${basePath}${API_ROUTE_SHAREABLE_ZIP}`, JSON.stringify(renderedWorkpad))
|
.post(`${basePath}${API_ROUTE_SHAREABLE_ZIP}`, JSON.stringify(renderedWorkpad))
|
||||||
.then(blob => downloadZippedRuntime(blob.data))
|
.then(blob => downloadZippedRuntime(blob.data))
|
||||||
.catch((err: Error) => {
|
.catch((err: Error) => {
|
||||||
notify.error(err, { title: strings.getShareableZipErrorTitle(workpad.name) });
|
kibana.services.canvas.notify.error(err, {
|
||||||
|
title: strings.getShareableZipErrorTitle(workpad.name),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -8,8 +8,6 @@ import { connect } from 'react-redux';
|
||||||
import { compose, withProps } from 'recompose';
|
import { compose, withProps } from 'recompose';
|
||||||
import { jobCompletionNotifications } from '../../../../../../../plugins/reporting/public';
|
import { jobCompletionNotifications } from '../../../../../../../plugins/reporting/public';
|
||||||
import { getWorkpad, getPages } from '../../../state/selectors/workpad';
|
import { getWorkpad, getPages } from '../../../state/selectors/workpad';
|
||||||
// @ts-ignore Untyped local
|
|
||||||
import { notify } from '../../../lib/notify';
|
|
||||||
import { getWindow } from '../../../lib/get_window';
|
import { getWindow } from '../../../lib/get_window';
|
||||||
import { downloadWorkpad } from '../../../lib/download_workpad';
|
import { downloadWorkpad } from '../../../lib/download_workpad';
|
||||||
import { ShareMenu as Component, Props as ComponentProps } from './share_menu';
|
import { ShareMenu as Component, Props as ComponentProps } from './share_menu';
|
||||||
|
@ -59,10 +57,10 @@ export const ShareMenu = compose<ComponentProps, {}>(
|
||||||
onCopy: type => {
|
onCopy: type => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'pdf':
|
case 'pdf':
|
||||||
notify.info(strings.getCopyPDFMessage());
|
kibana.services.canvas.notify.info(strings.getCopyPDFMessage());
|
||||||
break;
|
break;
|
||||||
case 'reportingConfig':
|
case 'reportingConfig':
|
||||||
notify.info(strings.getCopyReportingConfigMessage());
|
kibana.services.canvas.notify.info(strings.getCopyReportingConfigMessage());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(strings.getUnknownExportErrorMessage(type));
|
throw new Error(strings.getUnknownExportErrorMessage(type));
|
||||||
|
@ -73,7 +71,7 @@ export const ShareMenu = compose<ComponentProps, {}>(
|
||||||
case 'pdf':
|
case 'pdf':
|
||||||
return createPdf(workpad, { pageCount }, kibana.services.http.basePath)
|
return createPdf(workpad, { pageCount }, kibana.services.http.basePath)
|
||||||
.then(({ data }: { data: { job: { id: string } } }) => {
|
.then(({ data }: { data: { job: { id: string } } }) => {
|
||||||
notify.info(strings.getExportPDFMessage(), {
|
kibana.services.canvas.notify.info(strings.getExportPDFMessage(), {
|
||||||
title: strings.getExportPDFTitle(workpad.name),
|
title: strings.getExportPDFTitle(workpad.name),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -81,7 +79,9 @@ export const ShareMenu = compose<ComponentProps, {}>(
|
||||||
jobCompletionNotifications.add(data.job.id);
|
jobCompletionNotifications.add(data.job.id);
|
||||||
})
|
})
|
||||||
.catch((err: Error) => {
|
.catch((err: Error) => {
|
||||||
notify.error(err, { title: strings.getExportPDFErrorTitle(workpad.name) });
|
kibana.services.canvas.notify.error(err, {
|
||||||
|
title: strings.getExportPDFErrorTitle(workpad.name),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
case 'json':
|
case 'json':
|
||||||
downloadWorkpad(workpad.id);
|
downloadWorkpad(workpad.id);
|
||||||
|
|
|
@ -9,8 +9,6 @@ import { compose, withHandlers } from 'recompose';
|
||||||
import { Dispatch } from 'redux';
|
import { Dispatch } from 'redux';
|
||||||
import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public/';
|
import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public/';
|
||||||
import { zoomHandlerCreators } from '../../../lib/app_handler_creators';
|
import { zoomHandlerCreators } from '../../../lib/app_handler_creators';
|
||||||
// @ts-ignore Untyped local
|
|
||||||
import { notify } from '../../../lib/notify';
|
|
||||||
import { State, CanvasWorkpadBoundingBox } from '../../../../types';
|
import { State, CanvasWorkpadBoundingBox } from '../../../../types';
|
||||||
// @ts-ignore Untyped local
|
// @ts-ignore Untyped local
|
||||||
import { fetchAllRenderables } from '../../../state/actions/elements';
|
import { fetchAllRenderables } from '../../../state/actions/elements';
|
||||||
|
|
|
@ -9,7 +9,6 @@ import { connect } from 'react-redux';
|
||||||
import { compose, withState, getContext, withHandlers, withProps } from 'recompose';
|
import { compose, withState, getContext, withHandlers, withProps } from 'recompose';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import * as workpadService from '../../lib/workpad_service';
|
import * as workpadService from '../../lib/workpad_service';
|
||||||
import { notify } from '../../lib/notify';
|
|
||||||
import { canUserWrite } from '../../state/selectors/app';
|
import { canUserWrite } from '../../state/selectors/app';
|
||||||
import { getWorkpad } from '../../state/selectors/workpad';
|
import { getWorkpad } from '../../state/selectors/workpad';
|
||||||
import { getId } from '../../lib/get_id';
|
import { getId } from '../../lib/get_id';
|
||||||
|
@ -32,7 +31,11 @@ export const WorkpadLoader = compose(
|
||||||
}),
|
}),
|
||||||
connect(mapStateToProps),
|
connect(mapStateToProps),
|
||||||
withState('workpads', 'setWorkpads', null),
|
withState('workpads', 'setWorkpads', null),
|
||||||
withHandlers({
|
withKibana,
|
||||||
|
withProps(({ kibana }) => ({
|
||||||
|
notify: kibana.services.canvas.notify,
|
||||||
|
})),
|
||||||
|
withHandlers(({ kibana }) => ({
|
||||||
// Workpad creation via navigation
|
// Workpad creation via navigation
|
||||||
createWorkpad: props => async workpad => {
|
createWorkpad: props => async workpad => {
|
||||||
// workpad data uploaded, create and load it
|
// workpad data uploaded, create and load it
|
||||||
|
@ -41,7 +44,9 @@ export const WorkpadLoader = compose(
|
||||||
await workpadService.create(workpad);
|
await workpadService.create(workpad);
|
||||||
props.router.navigateTo('loadWorkpad', { id: workpad.id, page: 1 });
|
props.router.navigateTo('loadWorkpad', { id: workpad.id, page: 1 });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: errors.getUploadFailureErrorMessage() });
|
kibana.services.canvas.notify.error(err, {
|
||||||
|
title: errors.getUploadFailureErrorMessage(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +60,7 @@ export const WorkpadLoader = compose(
|
||||||
const workpads = await workpadService.find(text);
|
const workpads = await workpadService.find(text);
|
||||||
setWorkpads(workpads);
|
setWorkpads(workpads);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: errors.getFindFailureErrorMessage() });
|
kibana.services.canvas.notify.error(err, { title: errors.getFindFailureErrorMessage() });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -71,7 +76,7 @@ export const WorkpadLoader = compose(
|
||||||
await workpadService.create(workpad);
|
await workpadService.create(workpad);
|
||||||
props.router.navigateTo('loadWorkpad', { id: workpad.id, page: 1 });
|
props.router.navigateTo('loadWorkpad', { id: workpad.id, page: 1 });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: errors.getCloneFailureErrorMessage() });
|
kibana.services.canvas.notify.error(err, { title: errors.getCloneFailureErrorMessage() });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -92,7 +97,7 @@ export const WorkpadLoader = compose(
|
||||||
return Promise.all(removeWorkpads).then(results => {
|
return Promise.all(removeWorkpads).then(results => {
|
||||||
let redirectHome = false;
|
let redirectHome = false;
|
||||||
|
|
||||||
const [passes, errors] = results.reduce(
|
const [passes, errored] = results.reduce(
|
||||||
([passes, errors], result) => {
|
([passes, errors], result) => {
|
||||||
if (result.id === loadedWorkpad && !result.err) {
|
if (result.id === loadedWorkpad && !result.err) {
|
||||||
redirectHome = true;
|
redirectHome = true;
|
||||||
|
@ -116,8 +121,8 @@ export const WorkpadLoader = compose(
|
||||||
workpads: remainingWorkpads,
|
workpads: remainingWorkpads,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (errors.length > 0) {
|
if (errored.length > 0) {
|
||||||
notify.error(errors.getDeleteFailureErrorMessage());
|
kibana.services.canvas.notify.error(errors.getDeleteFailureErrorMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
setWorkpads(workpadState);
|
setWorkpads(workpadState);
|
||||||
|
@ -126,11 +131,10 @@ export const WorkpadLoader = compose(
|
||||||
props.router.navigateTo('home');
|
props.router.navigateTo('home');
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.map(({ id }) => id);
|
return errored.map(({ id }) => id);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}),
|
})),
|
||||||
withKibana,
|
|
||||||
withProps(props => ({
|
withProps(props => ({
|
||||||
formatDate: date => {
|
formatDate: date => {
|
||||||
const dateFormat = props.kibana.services.uiSettings.get('dateFormat');
|
const dateFormat = props.kibana.services.uiSettings.get('dateFormat');
|
||||||
|
|
|
@ -6,12 +6,11 @@
|
||||||
|
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { getId } from '../../lib/get_id';
|
import { getId } from '../../lib/get_id';
|
||||||
import { notify } from '../../lib/notify';
|
|
||||||
import { ErrorStrings } from '../../../i18n';
|
import { ErrorStrings } from '../../../i18n';
|
||||||
|
|
||||||
const { WorkpadFileUpload: errors } = ErrorStrings;
|
const { WorkpadFileUpload: errors } = ErrorStrings;
|
||||||
|
|
||||||
export const uploadWorkpad = (file, onUpload) => {
|
export const uploadWorkpad = (file, onUpload, notify) => {
|
||||||
if (!file) {
|
if (!file) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { compose, withHandlers } from 'recompose';
|
import { compose, withHandlers } from 'recompose';
|
||||||
import { notify } from '../../../lib/notify';
|
|
||||||
import { uploadWorkpad } from '../upload_workpad';
|
import { uploadWorkpad } from '../upload_workpad';
|
||||||
import { ErrorStrings } from '../../../../i18n';
|
import { ErrorStrings } from '../../../../i18n';
|
||||||
import { WorkpadDropzone as Component } from './workpad_dropzone';
|
import { WorkpadDropzone as Component } from './workpad_dropzone';
|
||||||
|
@ -14,7 +13,7 @@ import { WorkpadDropzone as Component } from './workpad_dropzone';
|
||||||
const { WorkpadFileUpload: errors } = ErrorStrings;
|
const { WorkpadFileUpload: errors } = ErrorStrings;
|
||||||
|
|
||||||
export const WorkpadDropzone = compose(
|
export const WorkpadDropzone = compose(
|
||||||
withHandlers({
|
withHandlers(({ notify }) => ({
|
||||||
onDropAccepted: ({ onUpload }) => ([file]) => uploadWorkpad(file, onUpload),
|
onDropAccepted: ({ onUpload }) => ([file]) => uploadWorkpad(file, onUpload),
|
||||||
onDropRejected: () => ([file]) => {
|
onDropRejected: () => ([file]) => {
|
||||||
notify.warning(errors.getAcceptJSONOnlyErrorMessage(), {
|
notify.warning(errors.getAcceptJSONOnlyErrorMessage(), {
|
||||||
|
@ -23,7 +22,7 @@ export const WorkpadDropzone = compose(
|
||||||
: errors.getFileUploadFailureWithoutFileNameErrorMessage(),
|
: errors.getFileUploadFailureWithoutFileNameErrorMessage(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
})
|
}))
|
||||||
)(Component);
|
)(Component);
|
||||||
|
|
||||||
WorkpadDropzone.propTypes = {
|
WorkpadDropzone.propTypes = {
|
||||||
|
|
|
@ -249,7 +249,11 @@ export class WorkpadLoader extends React.PureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<WorkpadDropzone onUpload={this.onUpload} disabled={createPending || !canUserWrite}>
|
<WorkpadDropzone
|
||||||
|
onUpload={this.onUpload}
|
||||||
|
disabled={createPending || !canUserWrite}
|
||||||
|
notify={this.props.notify}
|
||||||
|
>
|
||||||
<EuiBasicTable
|
<EuiBasicTable
|
||||||
items={rows}
|
items={rows}
|
||||||
itemId="id"
|
itemId="id"
|
||||||
|
@ -327,7 +331,7 @@ export class WorkpadLoader extends React.PureComponent {
|
||||||
compressed
|
compressed
|
||||||
className="canvasWorkpad__upload--compressed"
|
className="canvasWorkpad__upload--compressed"
|
||||||
initialPromptText={strings.getFilePickerPlaceholder()}
|
initialPromptText={strings.getFilePickerPlaceholder()}
|
||||||
onChange={([file]) => uploadWorkpad(file, this.onUpload)}
|
onChange={([file]) => uploadWorkpad(file, this.onUpload, this.props.notify)}
|
||||||
accept="application/json"
|
accept="application/json"
|
||||||
disabled={createPending || !canUserWrite}
|
disabled={createPending || !canUserWrite}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { compose, getContext, withHandlers, withProps } from 'recompose';
|
import { compose, getContext, withHandlers, withProps } from 'recompose';
|
||||||
import * as workpadService from '../../lib/workpad_service';
|
import * as workpadService from '../../lib/workpad_service';
|
||||||
import { notify } from '../../lib/notify';
|
|
||||||
import { getId } from '../../lib/get_id';
|
import { getId } from '../../lib/get_id';
|
||||||
import { templatesRegistry } from '../../lib/templates_registry';
|
import { templatesRegistry } from '../../lib/templates_registry';
|
||||||
|
import { withKibana } from '../../../../../../../src/plugins/kibana_react/public';
|
||||||
import { WorkpadTemplates as Component } from './workpad_templates';
|
import { WorkpadTemplates as Component } from './workpad_templates';
|
||||||
|
|
||||||
export const WorkpadTemplates = compose(
|
export const WorkpadTemplates = compose(
|
||||||
|
@ -19,7 +19,8 @@ export const WorkpadTemplates = compose(
|
||||||
withProps(() => ({
|
withProps(() => ({
|
||||||
templates: templatesRegistry.toJS(),
|
templates: templatesRegistry.toJS(),
|
||||||
})),
|
})),
|
||||||
withHandlers({
|
withKibana,
|
||||||
|
withHandlers(({ kibana }) => ({
|
||||||
// Clone workpad given an id
|
// Clone workpad given an id
|
||||||
cloneWorkpad: props => workpad => {
|
cloneWorkpad: props => workpad => {
|
||||||
workpad.id = getId('workpad');
|
workpad.id = getId('workpad');
|
||||||
|
@ -31,7 +32,9 @@ export const WorkpadTemplates = compose(
|
||||||
return workpadService
|
return workpadService
|
||||||
.create(workpad)
|
.create(workpad)
|
||||||
.then(() => props.router.navigateTo('loadWorkpad', { id: workpad.id, page: 1 }))
|
.then(() => props.router.navigateTo('loadWorkpad', { id: workpad.id, page: 1 }))
|
||||||
.catch(err => notify.error(err, { title: `Couldn't clone workpad template` }));
|
.catch(err =>
|
||||||
|
kibana.services.canvas.notify.error(err, { title: `Couldn't clone workpad template` })
|
||||||
|
);
|
||||||
},
|
},
|
||||||
})
|
}))
|
||||||
)(Component);
|
)(Component);
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
CoreStart,
|
CoreStart,
|
||||||
} from '../../../../../src/core/public';
|
} from '../../../../../src/core/public';
|
||||||
import { CanvasSetup, CanvasStart, CanvasSetupDeps, CanvasStartDeps, CanvasPlugin } from './plugin';
|
import { CanvasSetup, CanvasStart, CanvasSetupDeps, CanvasStartDeps, CanvasPlugin } from './plugin';
|
||||||
|
import { CanvasServices } from './services';
|
||||||
|
|
||||||
export const plugin: PluginInitializer<
|
export const plugin: PluginInitializer<
|
||||||
CanvasSetup,
|
CanvasSetup,
|
||||||
|
@ -22,7 +23,7 @@ export const plugin: PluginInitializer<
|
||||||
|
|
||||||
export interface WithKibanaProps {
|
export interface WithKibanaProps {
|
||||||
kibana: {
|
kibana: {
|
||||||
services: CoreStart & CanvasStartDeps;
|
services: CoreStart & CanvasStartDeps & { canvas: CanvasServices };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
import fileSaver from 'file-saver';
|
import fileSaver from 'file-saver';
|
||||||
import { API_ROUTE_SHAREABLE_RUNTIME_DOWNLOAD } from '../../common/lib/constants';
|
import { API_ROUTE_SHAREABLE_RUNTIME_DOWNLOAD } from '../../common/lib/constants';
|
||||||
import { ErrorStrings } from '../../i18n';
|
import { ErrorStrings } from '../../i18n';
|
||||||
// @ts-ignore untyped local
|
import { notifyService } from '../services';
|
||||||
import { notify } from './notify';
|
|
||||||
// @ts-ignore untyped local
|
// @ts-ignore untyped local
|
||||||
import * as workpadService from './workpad_service';
|
import * as workpadService from './workpad_service';
|
||||||
import { CanvasRenderedWorkpad } from '../../shareable_runtime/types';
|
import { CanvasRenderedWorkpad } from '../../shareable_runtime/types';
|
||||||
|
@ -20,7 +19,7 @@ export const downloadWorkpad = async (workpadId: string) => {
|
||||||
const jsonBlob = new Blob([JSON.stringify(workpad)], { type: 'application/json' });
|
const jsonBlob = new Blob([JSON.stringify(workpad)], { type: 'application/json' });
|
||||||
fileSaver.saveAs(jsonBlob, `canvas-workpad-${workpad.name}-${workpad.id}.json`);
|
fileSaver.saveAs(jsonBlob, `canvas-workpad-${workpad.name}-${workpad.id}.json`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: strings.getDownloadFailureErrorMessage() });
|
notifyService.getService().error(err, { title: strings.getDownloadFailureErrorMessage() });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,7 +31,9 @@ export const downloadRenderedWorkpad = async (renderedWorkpad: CanvasRenderedWor
|
||||||
`canvas-embed-workpad-${renderedWorkpad.name}-${renderedWorkpad.id}.json`
|
`canvas-embed-workpad-${renderedWorkpad.name}-${renderedWorkpad.id}.json`
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: strings.getDownloadRenderedWorkpadFailureErrorMessage() });
|
notifyService
|
||||||
|
.getService()
|
||||||
|
.error(err, { title: strings.getDownloadRenderedWorkpadFailureErrorMessage() });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,7 +43,9 @@ export const downloadRuntime = async (basePath: string) => {
|
||||||
window.open(path);
|
window.open(path);
|
||||||
return;
|
return;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: strings.getDownloadRuntimeFailureErrorMessage() });
|
notifyService
|
||||||
|
.getService()
|
||||||
|
.error(err, { title: strings.getDownloadRuntimeFailureErrorMessage() });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,6 +54,8 @@ export const downloadZippedRuntime = async (data: any) => {
|
||||||
const zip = new Blob([data], { type: 'octet/stream' });
|
const zip = new Blob([data], { type: 'octet/stream' });
|
||||||
fileSaver.saveAs(zip, 'canvas-workpad-embed.zip');
|
fileSaver.saveAs(zip, 'canvas-workpad-embed.zip');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err, { title: strings.getDownloadZippedRuntimeFailureErrorMessage() });
|
notifyService
|
||||||
|
.getService()
|
||||||
|
.error(err, { title: strings.getDownloadZippedRuntimeFailureErrorMessage() });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,14 +4,12 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Http2ServerResponse } from 'http2';
|
|
||||||
import { camelCase } from 'lodash';
|
import { camelCase } from 'lodash';
|
||||||
// @ts-ignore unconverted local file
|
// @ts-ignore unconverted local file
|
||||||
import { getClipboardData, setClipboardData } from './clipboard';
|
import { getClipboardData, setClipboardData } from './clipboard';
|
||||||
// @ts-ignore unconverted local file
|
// @ts-ignore unconverted local file
|
||||||
import { cloneSubgraphs } from './clone_subgraphs';
|
import { cloneSubgraphs } from './clone_subgraphs';
|
||||||
// @ts-ignore unconverted local file
|
import { notifyService } from '../services';
|
||||||
import { notify } from './notify';
|
|
||||||
import * as customElementService from './custom_element_service';
|
import * as customElementService from './custom_element_service';
|
||||||
import { getId } from './get_id';
|
import { getId } from './get_id';
|
||||||
import { PositionedElement } from '../../types';
|
import { PositionedElement } from '../../types';
|
||||||
|
@ -86,15 +84,17 @@ export const basicHandlerCreators = {
|
||||||
customElementService
|
customElementService
|
||||||
.create(customElement)
|
.create(customElement)
|
||||||
.then(() =>
|
.then(() =>
|
||||||
notify.success(
|
notifyService
|
||||||
`Custom element '${customElement.displayName || customElement.id}' was saved`,
|
.getService()
|
||||||
{
|
.success(
|
||||||
'data-test-subj': 'canvasCustomElementCreate-success',
|
`Custom element '${customElement.displayName || customElement.id}' was saved`,
|
||||||
}
|
{
|
||||||
)
|
'data-test-subj': 'canvasCustomElementCreate-success',
|
||||||
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.catch((result: Http2ServerResponse) =>
|
.catch((error: Error) =>
|
||||||
notify.warning(result, {
|
notifyService.getService().warning(error, {
|
||||||
title: `Custom element '${customElement.displayName ||
|
title: `Custom element '${customElement.displayName ||
|
||||||
customElement.id}' was not saved`,
|
customElement.id}' was not saved`,
|
||||||
})
|
})
|
||||||
|
@ -138,13 +138,13 @@ export const clipboardHandlerCreators = {
|
||||||
if (selectedNodes.length) {
|
if (selectedNodes.length) {
|
||||||
setClipboardData({ selectedNodes });
|
setClipboardData({ selectedNodes });
|
||||||
removeNodes(selectedNodes.map(extractId), pageId);
|
removeNodes(selectedNodes.map(extractId), pageId);
|
||||||
notify.success('Cut element to clipboard');
|
notifyService.getService().success('Cut element to clipboard');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
copyNodes: ({ selectedNodes }: Props) => (): void => {
|
copyNodes: ({ selectedNodes }: Props) => (): void => {
|
||||||
if (selectedNodes.length) {
|
if (selectedNodes.length) {
|
||||||
setClipboardData({ selectedNodes });
|
setClipboardData({ selectedNodes });
|
||||||
notify.success('Copied element to clipboard');
|
notifyService.getService().success('Copied element to clipboard');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pasteNodes: ({ insertNodes, pageId, selectToplevelNodes }: Props) => (): void => {
|
pasteNodes: ({ insertNodes, pageId, selectToplevelNodes }: Props) => (): void => {
|
||||||
|
|
|
@ -10,8 +10,7 @@ import { API_ROUTE } from '../../common/lib/constants';
|
||||||
// @ts-ignore untyped local
|
// @ts-ignore untyped local
|
||||||
import { fetch } from '../../common/lib/fetch';
|
import { fetch } from '../../common/lib/fetch';
|
||||||
import { ErrorStrings } from '../../i18n';
|
import { ErrorStrings } from '../../i18n';
|
||||||
// @ts-ignore untyped local
|
import { notifyService } from '../services';
|
||||||
import { notify } from './notify';
|
|
||||||
import { getCoreStart } from '../legacy';
|
import { getCoreStart } from '../legacy';
|
||||||
|
|
||||||
const { esService: strings } = ErrorStrings;
|
const { esService: strings } = ErrorStrings;
|
||||||
|
@ -38,7 +37,7 @@ export const getFields = (index = '_all') => {
|
||||||
.sort()
|
.sort()
|
||||||
)
|
)
|
||||||
.catch((err: Error) =>
|
.catch((err: Error) =>
|
||||||
notify.error(err, {
|
notifyService.getService().error(err, {
|
||||||
title: strings.getFieldsFetchErrorMessage(index),
|
title: strings.getFieldsFetchErrorMessage(index),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -57,7 +56,9 @@ export const getIndices = () =>
|
||||||
return savedObject.attributes.title;
|
return savedObject.attributes.title;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err: Error) => notify.error(err, { title: strings.getIndicesFetchErrorMessage() }));
|
.catch((err: Error) =>
|
||||||
|
notifyService.getService().error(err, { title: strings.getIndicesFetchErrorMessage() })
|
||||||
|
);
|
||||||
|
|
||||||
export const getDefaultIndex = () => {
|
export const getDefaultIndex = () => {
|
||||||
const defaultIndexId = getAdvancedSettings().get('defaultIndex');
|
const defaultIndexId = getAdvancedSettings().get('defaultIndex');
|
||||||
|
@ -66,6 +67,10 @@ export const getDefaultIndex = () => {
|
||||||
? getSavedObjectsClient()
|
? getSavedObjectsClient()
|
||||||
.get<IndexPatternAttributes>('index-pattern', defaultIndexId)
|
.get<IndexPatternAttributes>('index-pattern', defaultIndexId)
|
||||||
.then(defaultIndex => defaultIndex.attributes.title)
|
.then(defaultIndex => defaultIndex.attributes.title)
|
||||||
.catch(err => notify.error(err, { title: strings.getDefaultIndexFetchErrorMessage() }))
|
.catch(err =>
|
||||||
|
notifyService
|
||||||
|
.getService()
|
||||||
|
.error(err, { title: strings.getDefaultIndexFetchErrorMessage() })
|
||||||
|
)
|
||||||
: Promise.resolve('');
|
: Promise.resolve('');
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License;
|
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { get } from 'lodash';
|
|
||||||
import { getCoreStart, getStartPlugins } from '../legacy';
|
|
||||||
|
|
||||||
const getToastNotifications = function() {
|
|
||||||
return getCoreStart().notifications.toasts;
|
|
||||||
};
|
|
||||||
|
|
||||||
const formatMsg = function(...args) {
|
|
||||||
return getStartPlugins().__LEGACY.formatMsg(...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getToast = (err, opts = {}) => {
|
|
||||||
const errData = get(err, 'response') || err;
|
|
||||||
const errMsg = formatMsg(errData);
|
|
||||||
const { title, ...rest } = opts;
|
|
||||||
let text = null;
|
|
||||||
|
|
||||||
if (title) {
|
|
||||||
text = errMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...rest,
|
|
||||||
title: title || errMsg,
|
|
||||||
text,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const notify = {
|
|
||||||
/*
|
|
||||||
* @param {(string | Object)} err: message or Error object
|
|
||||||
* @param {Object} opts: option to override toast title or icon, see https://github.com/elastic/kibana/blob/master/src/legacy/ui/public/notify/toasts/TOAST_NOTIFICATIONS.md
|
|
||||||
*/
|
|
||||||
error(err, opts) {
|
|
||||||
getToastNotifications().addDanger(getToast(err, opts));
|
|
||||||
},
|
|
||||||
warning(err, opts) {
|
|
||||||
getToastNotifications().addWarning(getToast(err, opts));
|
|
||||||
},
|
|
||||||
info(err, opts) {
|
|
||||||
getToastNotifications().add(getToast(err, opts));
|
|
||||||
},
|
|
||||||
success(err, opts) {
|
|
||||||
getToastNotifications().addSuccess(getToast(err, opts));
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
import { fromExpression, getType } from '@kbn/interpreter/common';
|
import { fromExpression, getType } from '@kbn/interpreter/common';
|
||||||
import { ExpressionValue, ExpressionAstExpression } from 'src/plugins/expressions/public';
|
import { ExpressionValue, ExpressionAstExpression } from 'src/plugins/expressions/public';
|
||||||
// @ts-ignore Untyped Local
|
import { notifyService } from '../services';
|
||||||
import { notify } from './notify';
|
|
||||||
|
|
||||||
import { CanvasStartDeps, CanvasSetupDeps } from '../plugin';
|
import { CanvasStartDeps, CanvasSetupDeps } from '../plugin';
|
||||||
|
|
||||||
|
@ -85,7 +84,7 @@ export async function runInterpreter(
|
||||||
|
|
||||||
throw new Error(`Ack! I don't know how to render a '${getType(renderable)}'`);
|
throw new Error(`Ack! I don't know how to render a '${getType(renderable)}'`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err);
|
notifyService.getService().error(err);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
73
x-pack/legacy/plugins/canvas/public/services/index.ts
Normal file
73
x-pack/legacy/plugins/canvas/public/services/index.ts
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { CoreSetup, CoreStart } from '../../../../../../src/core/public';
|
||||||
|
import { CanvasSetupDeps, CanvasStartDeps } from '../plugin';
|
||||||
|
import { notifyServiceFactory } from './notify';
|
||||||
|
|
||||||
|
export type CanvasServiceFactory<Service> = (
|
||||||
|
coreSetup: CoreSetup,
|
||||||
|
coreStart: CoreStart,
|
||||||
|
canvasSetupPlugins: CanvasSetupDeps,
|
||||||
|
canvasStartPlugins: CanvasStartDeps
|
||||||
|
) => Service;
|
||||||
|
|
||||||
|
class CanvasServiceProvider<Service> {
|
||||||
|
private factory: CanvasServiceFactory<Service>;
|
||||||
|
private service: Service | undefined;
|
||||||
|
|
||||||
|
constructor(factory: CanvasServiceFactory<Service>) {
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
start(
|
||||||
|
coreSetup: CoreSetup,
|
||||||
|
coreStart: CoreStart,
|
||||||
|
canvasSetupPlugins: CanvasSetupDeps,
|
||||||
|
canvasStartPlugins: CanvasStartDeps
|
||||||
|
) {
|
||||||
|
this.service = this.factory(coreSetup, coreStart, canvasSetupPlugins, canvasStartPlugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
getService(): Service {
|
||||||
|
if (!this.service) {
|
||||||
|
throw new Error('Service not ready');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.service;
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
this.service = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ServiceFromProvider<P> = P extends CanvasServiceProvider<infer T> ? T : never;
|
||||||
|
|
||||||
|
export const services = {
|
||||||
|
notify: new CanvasServiceProvider(notifyServiceFactory),
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface CanvasServices {
|
||||||
|
notify: ServiceFromProvider<typeof services.notify>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const startServices = (
|
||||||
|
coreSetup: CoreSetup,
|
||||||
|
coreStart: CoreStart,
|
||||||
|
canvasSetupPlugins: CanvasSetupDeps,
|
||||||
|
canvasStartPlugins: CanvasStartDeps
|
||||||
|
) => {
|
||||||
|
Object.entries(services).forEach(([key, provider]) =>
|
||||||
|
provider.start(coreSetup, coreStart, canvasSetupPlugins, canvasStartPlugins)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const stopServices = () => {
|
||||||
|
Object.entries(services).forEach(([key, provider]) => provider.stop());
|
||||||
|
};
|
||||||
|
|
||||||
|
export const { notify: notifyService } = services;
|
57
x-pack/legacy/plugins/canvas/public/services/notify.ts
Normal file
57
x-pack/legacy/plugins/canvas/public/services/notify.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { get } from 'lodash';
|
||||||
|
import { CanvasServiceFactory } from '.';
|
||||||
|
import { formatMsg } from '../../../../../../src/plugins/kibana_legacy/public';
|
||||||
|
import { ToastInputFields } from '../../../../../../src/core/public';
|
||||||
|
|
||||||
|
const getToast = (err: Error | string, opts: ToastInputFields = {}) => {
|
||||||
|
const errData = (get(err, 'response') || err) as Error | string;
|
||||||
|
const errMsg = formatMsg(errData);
|
||||||
|
const { title, ...rest } = opts;
|
||||||
|
let text;
|
||||||
|
|
||||||
|
if (title) {
|
||||||
|
text = errMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
title: title || errMsg,
|
||||||
|
text,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
interface NotifyService {
|
||||||
|
error: (err: string | Error, opts?: ToastInputFields) => void;
|
||||||
|
warning: (err: string | Error, opts?: ToastInputFields) => void;
|
||||||
|
info: (err: string | Error, opts?: ToastInputFields) => void;
|
||||||
|
success: (err: string | Error, opts?: ToastInputFields) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const notifyServiceFactory: CanvasServiceFactory<NotifyService> = (setup, start) => {
|
||||||
|
const toasts = start.notifications.toasts;
|
||||||
|
|
||||||
|
return {
|
||||||
|
/*
|
||||||
|
* @param {(string | Object)} err: message or Error object
|
||||||
|
* @param {Object} opts: option to override toast title or icon, see https://github.com/elastic/kibana/blob/master/src/legacy/ui/public/notify/toasts/TOAST_NOTIFICATIONS.md
|
||||||
|
*/
|
||||||
|
error(err, opts) {
|
||||||
|
toasts.addDanger(getToast(err, opts));
|
||||||
|
},
|
||||||
|
warning(err, opts) {
|
||||||
|
toasts.addWarning(getToast(err, opts));
|
||||||
|
},
|
||||||
|
info(err, opts) {
|
||||||
|
toasts.add(getToast(err, opts));
|
||||||
|
},
|
||||||
|
success(err, opts) {
|
||||||
|
toasts.addSuccess(getToast(err, opts));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
|
@ -13,9 +13,9 @@ import { getPages, getNodeById, getNodes, getSelectedPageIndex } from '../select
|
||||||
import { getValue as getResolvedArgsValue } from '../selectors/resolved_args';
|
import { getValue as getResolvedArgsValue } from '../selectors/resolved_args';
|
||||||
import { getDefaultElement } from '../defaults';
|
import { getDefaultElement } from '../defaults';
|
||||||
import { ErrorStrings } from '../../../i18n';
|
import { ErrorStrings } from '../../../i18n';
|
||||||
import { notify } from '../../lib/notify';
|
|
||||||
import { runInterpreter, interpretAst } from '../../lib/run_interpreter';
|
import { runInterpreter, interpretAst } from '../../lib/run_interpreter';
|
||||||
import { subMultitree } from '../../lib/aeroelastic/functional';
|
import { subMultitree } from '../../lib/aeroelastic/functional';
|
||||||
|
import { services } from '../../services';
|
||||||
import { selectToplevelNodes } from './transient';
|
import { selectToplevelNodes } from './transient';
|
||||||
import * as args from './resolved_args';
|
import * as args from './resolved_args';
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ const fetchRenderableWithContextFn = ({ dispatch }, element, ast, context) => {
|
||||||
dispatch(getAction(renderable));
|
dispatch(getAction(renderable));
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
notify.error(err);
|
services.notify.getService().error(err);
|
||||||
dispatch(getAction(err));
|
dispatch(getAction(err));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -176,7 +176,7 @@ export const fetchAllRenderables = createThunk(
|
||||||
return runInterpreter(ast, null, { castToRender: true })
|
return runInterpreter(ast, null, { castToRender: true })
|
||||||
.then(renderable => ({ path: argumentPath, value: renderable }))
|
.then(renderable => ({ path: argumentPath, value: renderable }))
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
notify.error(err);
|
services.notify.getService().error(err);
|
||||||
return { path: argumentPath, value: err };
|
return { path: argumentPath, value: err };
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -293,7 +293,7 @@ const setAst = createThunk('setAst', ({ dispatch }, ast, element, pageId, doRend
|
||||||
const expression = toExpression(ast);
|
const expression = toExpression(ast);
|
||||||
dispatch(setExpression(expression, element.id, pageId, doRender));
|
dispatch(setExpression(expression, element.id, pageId, doRender));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify.error(err);
|
services.notify.getService().error(err);
|
||||||
|
|
||||||
// TODO: remove this, may have been added just to cause a re-render, but why?
|
// TODO: remove this, may have been added just to cause a re-render, but why?
|
||||||
dispatch(setExpression(element.expression, element.id, pageId, doRender));
|
dispatch(setExpression(element.expression, element.id, pageId, doRender));
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { setAssets, resetAssets } from '../actions/assets';
|
||||||
import * as transientActions from '../actions/transient';
|
import * as transientActions from '../actions/transient';
|
||||||
import * as resolvedArgsActions from '../actions/resolved_args';
|
import * as resolvedArgsActions from '../actions/resolved_args';
|
||||||
import { update, updateAssets, updateWorkpad } from '../../lib/workpad_service';
|
import { update, updateAssets, updateWorkpad } from '../../lib/workpad_service';
|
||||||
import { notify } from '../../lib/notify';
|
import { services } from '../../services';
|
||||||
import { canUserWrite } from '../selectors/app';
|
import { canUserWrite } from '../selectors/app';
|
||||||
|
|
||||||
const { esPersist: strings } = ErrorStrings;
|
const { esPersist: strings } = ErrorStrings;
|
||||||
|
@ -62,15 +62,15 @@ export const esPersistMiddleware = ({ getState }) => {
|
||||||
const statusCode = err.response && err.response.status;
|
const statusCode = err.response && err.response.status;
|
||||||
switch (statusCode) {
|
switch (statusCode) {
|
||||||
case 400:
|
case 400:
|
||||||
return notify.error(err.response, {
|
return services.notify.getService().error(err.response, {
|
||||||
title: strings.getSaveFailureTitle(),
|
title: strings.getSaveFailureTitle(),
|
||||||
});
|
});
|
||||||
case 413:
|
case 413:
|
||||||
return notify.error(strings.getTooLargeErrorMessage(), {
|
return services.notify.getService().error(strings.getTooLargeErrorMessage(), {
|
||||||
title: strings.getSaveFailureTitle(),
|
title: strings.getSaveFailureTitle(),
|
||||||
});
|
});
|
||||||
default:
|
default:
|
||||||
return notify.error(err, {
|
return services.notify.getService().error(err, {
|
||||||
title: strings.getUpdateFailureTitle(),
|
title: strings.getUpdateFailureTitle(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue