[canvas] Create Notify Service; remove legacy service (#103821) (#104137)

Co-authored-by: Clint Andrew Hall <clint.hall@elastic.co>
This commit is contained in:
Kibana Machine 2021-07-01 14:16:40 -04:00 committed by GitHub
parent d953b3f672
commit 6bfc19031c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 145 additions and 96 deletions

View file

@ -9,7 +9,7 @@ import React, { FC } from 'react';
import { ExpressionFunction } from 'src/plugins/expressions';
import { EuiButtonEmpty } from '@elastic/eui';
import copy from 'copy-to-clipboard';
import { notifyService } from '../../services';
import { useNotifyService } from '../../services';
import { generateFunctionReference } from './generate_function_reference';
interface Props {
@ -17,16 +17,15 @@ interface Props {
}
export const FunctionReferenceGenerator: FC<Props> = ({ functionRegistry }) => {
const notifyService = useNotifyService();
const functionDefinitions = Object.values(functionRegistry);
const copyDocs = () => {
copy(generateFunctionReference(functionDefinitions));
notifyService
.getService()
.success(
`Please paste updated docs into '/kibana/docs/canvas/canvas-function-reference.asciidoc' and commit your changes.`,
{ title: 'Copied function docs to clipboard' }
);
notifyService.success(
`Please paste updated docs into '/kibana/docs/canvas/canvas-function-reference.asciidoc' and commit your changes.`,
{ title: 'Copied function docs to clipboard' }
);
};
return (

View file

@ -11,7 +11,7 @@ import { compose, withState } from 'recompose';
import { camelCase } from 'lodash';
import { cloneSubgraphs } from '../../lib/clone_subgraphs';
import * as customElementService from '../../lib/custom_element_service';
import { withServices, WithServicesProps } from '../../services';
import { withServices, WithServicesProps, pluginServices } from '../../services';
// @ts-expect-error untyped local
import { selectToplevelNodes } from '../../state/actions/transient';
// @ts-expect-error untyped local
@ -68,6 +68,7 @@ const mergeProps = (
dispatchProps: DispatchProps,
ownProps: OwnPropsWithState & WithServicesProps
): ComponentProps => {
const notifyService = pluginServices.getServices().notify;
const { pageId } = stateProps;
const { onClose, search, setCustomElements } = ownProps;
@ -94,7 +95,7 @@ const mergeProps = (
try {
await findCustomElements();
} catch (err) {
ownProps.services.notify.error(err, {
notifyService.error(err, {
title: `Couldn't find custom elements`,
});
}
@ -105,7 +106,7 @@ const mergeProps = (
await customElementService.remove(id);
await findCustomElements();
} catch (err) {
ownProps.services.notify.error(err, {
notifyService.error(err, {
title: `Couldn't delete custom elements`,
});
}
@ -121,7 +122,7 @@ const mergeProps = (
});
await findCustomElements();
} catch (err) {
ownProps.services.notify.error(err, {
notifyService.error(err, {
title: `Couldn't update custom elements`,
});
}

View file

@ -30,6 +30,7 @@ import { withKibana } from '../../../../../../../../src/plugins/kibana_react/pub
import { OnCloseFn } from '../share_menu.component';
import { ZIP } from '../../../../../i18n/constants';
import { WithKibanaProps } from '../../../../index';
import { pluginServices } from '../../../../services';
export { OnDownloadFn, OnCopyFn } from './flyout.component';
@ -95,7 +96,7 @@ export const ShareWebsiteFlyout = compose<ComponentProps, Pick<Props, 'onClose'>
unsupportedRenderers,
onClose,
onCopy: () => {
kibana.services.canvas.notify.info(strings.getCopyShareConfigMessage());
pluginServices.getServices().notify.info(strings.getCopyShareConfigMessage());
},
onDownload: (type) => {
switch (type) {
@ -111,7 +112,7 @@ export const ShareWebsiteFlyout = compose<ComponentProps, Pick<Props, 'onClose'>
.post(`${basePath}${API_ROUTE_SHAREABLE_ZIP}`, JSON.stringify(renderedWorkpad))
.then((blob) => downloadZippedRuntime(blob.data))
.catch((err: Error) => {
kibana.services.canvas.notify.error(err, {
pluginServices.getServices().notify.error(err, {
title: strings.getShareableZipErrorTitle(workpad.name),
});
});

View file

@ -8,7 +8,10 @@
import fileSaver from 'file-saver';
import { API_ROUTE_SHAREABLE_RUNTIME_DOWNLOAD } from '../../common/lib/constants';
import { ErrorStrings } from '../../i18n';
import { notifyService } from '../services';
// TODO: clint - convert this whole file to hooks
import { pluginServices } from '../services';
// @ts-expect-error untyped local
import * as workpadService from './workpad_service';
import { CanvasRenderedWorkpad } from '../../shareable_runtime/types';
@ -21,7 +24,8 @@ export const downloadWorkpad = async (workpadId: string) => {
const jsonBlob = new Blob([JSON.stringify(workpad)], { type: 'application/json' });
fileSaver.saveAs(jsonBlob, `canvas-workpad-${workpad.name}-${workpad.id}.json`);
} catch (err) {
notifyService.getService().error(err, { title: strings.getDownloadFailureErrorMessage() });
const notifyService = pluginServices.getServices().notify;
notifyService.error(err, { title: strings.getDownloadFailureErrorMessage() });
}
};
@ -33,9 +37,8 @@ export const downloadRenderedWorkpad = async (renderedWorkpad: CanvasRenderedWor
`canvas-embed-workpad-${renderedWorkpad.name}-${renderedWorkpad.id}.json`
);
} catch (err) {
notifyService
.getService()
.error(err, { title: strings.getDownloadRenderedWorkpadFailureErrorMessage() });
const notifyService = pluginServices.getServices().notify;
notifyService.error(err, { title: strings.getDownloadRenderedWorkpadFailureErrorMessage() });
}
};
@ -45,9 +48,8 @@ export const downloadRuntime = async (basePath: string) => {
window.open(path);
return;
} catch (err) {
notifyService
.getService()
.error(err, { title: strings.getDownloadRuntimeFailureErrorMessage() });
const notifyService = pluginServices.getServices().notify;
notifyService.error(err, { title: strings.getDownloadRuntimeFailureErrorMessage() });
}
};
@ -56,8 +58,7 @@ export const downloadZippedRuntime = async (data: any) => {
const zip = new Blob([data], { type: 'octet/stream' });
fileSaver.saveAs(zip, 'canvas-workpad-embed.zip');
} catch (err) {
notifyService
.getService()
.error(err, { title: strings.getDownloadZippedRuntimeFailureErrorMessage() });
const notifyService = pluginServices.getServices().notify;
notifyService.error(err, { title: strings.getDownloadZippedRuntimeFailureErrorMessage() });
}
};

View file

@ -8,7 +8,7 @@
import { camelCase } from 'lodash';
import { getClipboardData, setClipboardData } from './clipboard';
import { cloneSubgraphs } from './clone_subgraphs';
import { notifyService } from '../services';
import { pluginServices } from '../services';
import * as customElementService from './custom_element_service';
import { getId } from './get_id';
import { PositionedElement } from '../../types';
@ -70,6 +70,8 @@ export const basicHandlerCreators = {
description = '',
image = ''
): void => {
const notifyService = pluginServices.getServices().notify;
if (selectedNodes.length) {
const content = JSON.stringify({ selectedNodes });
const customElement = {
@ -83,17 +85,15 @@ export const basicHandlerCreators = {
customElementService
.create(customElement)
.then(() =>
notifyService
.getService()
.success(
`Custom element '${customElement.displayName || customElement.id}' was saved`,
{
'data-test-subj': 'canvasCustomElementCreate-success',
}
)
notifyService.success(
`Custom element '${customElement.displayName || customElement.id}' was saved`,
{
'data-test-subj': 'canvasCustomElementCreate-success',
}
)
)
.catch((error: Error) =>
notifyService.getService().warning(error, {
notifyService.warning(error, {
title: `Custom element '${
customElement.displayName || customElement.id
}' was not saved`,
@ -135,16 +135,20 @@ export const groupHandlerCreators = {
// handlers for cut/copy/paste
export const clipboardHandlerCreators = {
cutNodes: ({ pageId, removeNodes, selectedNodes }: Props) => (): void => {
const notifyService = pluginServices.getServices().notify;
if (selectedNodes.length) {
setClipboardData({ selectedNodes });
removeNodes(selectedNodes.map(extractId), pageId);
notifyService.getService().success('Cut element to clipboard');
notifyService.success('Cut element to clipboard');
}
},
copyNodes: ({ selectedNodes }: Props) => (): void => {
const notifyService = pluginServices.getServices().notify;
if (selectedNodes.length) {
setClipboardData({ selectedNodes });
notifyService.getService().success('Copied element to clipboard');
notifyService.success('Copied element to clipboard');
}
},
pasteNodes: ({ insertNodes, pageId, selectToplevelNodes }: Props) => (): void => {

View file

@ -5,12 +5,14 @@
* 2.0.
*/
// TODO - clint: convert to service abstraction
import { IndexPatternAttributes } from 'src/plugins/data/public';
import { API_ROUTE } from '../../common/lib/constants';
import { fetch } from '../../common/lib/fetch';
import { ErrorStrings } from '../../i18n';
import { notifyService } from '../services';
import { pluginServices } from '../services';
import { platformService } from '../services';
const { esService: strings } = ErrorStrings;
@ -36,11 +38,12 @@ export const getFields = (index = '_all') => {
.filter((field) => !field.startsWith('_')) // filters out meta fields
.sort()
)
.catch((err: Error) =>
notifyService.getService().error(err, {
.catch((err: Error) => {
const notifyService = pluginServices.getServices().notify;
notifyService.error(err, {
title: strings.getFieldsFetchErrorMessage(index),
})
);
});
});
};
export const getIndices = () =>
@ -56,9 +59,10 @@ export const getIndices = () =>
return savedObject.attributes.title;
});
})
.catch((err: Error) =>
notifyService.getService().error(err, { title: strings.getIndicesFetchErrorMessage() })
);
.catch((err: Error) => {
const notifyService = pluginServices.getServices().notify;
notifyService.error(err, { title: strings.getIndicesFetchErrorMessage() });
});
export const getDefaultIndex = () => {
const defaultIndexId = getAdvancedSettings().get('defaultIndex');
@ -67,10 +71,9 @@ export const getDefaultIndex = () => {
? getSavedObjectsClient()
.get<IndexPatternAttributes>('index-pattern', defaultIndexId)
.then((defaultIndex) => defaultIndex.attributes.title)
.catch((err) =>
notifyService
.getService()
.error(err, { title: strings.getDefaultIndexFetchErrorMessage() })
)
.catch((err) => {
const notifyService = pluginServices.getServices().notify;
notifyService.error(err, { title: strings.getDefaultIndexFetchErrorMessage() });
})
: Promise.resolve('');
};

View file

@ -7,7 +7,7 @@
import { fromExpression, getType } from '@kbn/interpreter/common';
import { ExpressionValue, ExpressionAstExpression } from 'src/plugins/expressions/public';
import { notifyService, expressionsService } from '../services';
import { pluginServices, expressionsService } from '../services';
interface Options {
castToRender?: boolean;
@ -57,7 +57,8 @@ export async function runInterpreter(
throw new Error(`Ack! I don't know how to render a '${getType(renderable)}'`);
} catch (err) {
notifyService.getService().error(err);
const { error: displayError } = pluginServices.getServices().notify;
displayError(err);
throw err;
}
}

View file

@ -13,7 +13,7 @@ import { ExportApp } from '../../components/export_app';
import { CanvasLoading } from '../../components/canvas_loading';
// @ts-expect-error
import { fetchAllRenderables } from '../../state/actions/elements';
import { useServices } from '../../services';
import { useNotifyService } from '../../services';
import { CanvasWorkpad } from '../../../types';
import { ErrorStrings } from '../../../i18n';
import { useWorkpad } from './hooks/use_workpad';
@ -98,13 +98,13 @@ const WorkpadLoaderComponent: FC<{
children: (workpad: CanvasWorkpad) => JSX.Element;
}> = ({ params, children, loadPages }) => {
const [workpad, error] = useWorkpad(params.id, loadPages);
const services = useServices();
const notifyService = useNotifyService();
useEffect(() => {
if (error) {
services.notify.error(error, { title: strings.getLoadFailureErrorMessage() });
notifyService.error(error, { title: strings.getLoadFailureErrorMessage() });
}
}, [error, services.notify]);
}, [error, notifyService]);
if (error) {
return <Redirect to="/" />;

View file

@ -9,11 +9,14 @@ export * from './legacy';
import { PluginServices } from '../../../../../src/plugins/presentation_util/public';
import { CanvasWorkpadService } from './workpad';
import { CanvasNotifyService } from './notify';
export interface CanvasPluginServices {
workpad: CanvasWorkpadService;
notify: CanvasNotifyService;
}
export const pluginServices = new PluginServices<CanvasPluginServices>();
export const useWorkpadService = () => (() => pluginServices.getHooks().workpad.useService())();
export const useNotifyService = () => (() => pluginServices.getHooks().notify.useService())();

View file

@ -13,16 +13,19 @@ import {
} from '../../../../../../src/plugins/presentation_util/public';
import { workpadServiceFactory } from './workpad';
import { notifyServiceFactory } from './notify';
import { CanvasPluginServices } from '..';
import { CanvasStartDeps } from '../../plugin';
export { workpadServiceFactory } from './workpad';
export { notifyServiceFactory } from './notify';
export const pluginServiceProviders: PluginServiceProviders<
CanvasPluginServices,
KibanaPluginServiceParams<CanvasStartDeps>
> = {
workpad: new PluginServiceProvider(workpadServiceFactory),
notify: new PluginServiceProvider(notifyServiceFactory),
};
export const pluginServiceRegistry = new PluginServiceRegistry<

View file

@ -6,9 +6,17 @@
*/
import { get } from 'lodash';
import { CanvasServiceFactory } from '.';
import { KibanaPluginServiceFactory } from '../../../../../../src/plugins/presentation_util/public';
import { formatMsg } from '../../../../../../src/plugins/kibana_legacy/public';
import { ToastInputFields } from '../../../../../../src/core/public';
import { CanvasStartDeps } from '../../plugin';
import { CanvasNotifyService } from '../notify';
export type CanvasNotifyServiceFactory = KibanaPluginServiceFactory<
CanvasNotifyService,
CanvasStartDeps
>;
const getToast = (err: Error | string, opts: ToastInputFields = {}) => {
const errData = (get(err, 'response') || err) as Error | string;
@ -28,15 +36,8 @@ const getToast = (err: Error | string, opts: ToastInputFields = {}) => {
};
};
export 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;
export const notifyServiceFactory: CanvasNotifyServiceFactory = ({ coreStart }) => {
const toasts = coreStart.notifications.toasts;
return {
/*

View file

@ -22,7 +22,6 @@ export interface WithServicesProps {
const defaultContextValue = {
embeddables: {},
expressions: {},
notify: {},
platform: {},
navLink: {},
search: {},
@ -34,7 +33,6 @@ export const useServices = () => useContext(context);
export const usePlatformService = () => useServices().platform;
export const useEmbeddablesService = () => useServices().embeddables;
export const useExpressionsService = () => useServices().expressions;
export const useNotifyService = () => useServices().notify;
export const useNavLinkService = () => useServices().navLink;
export const useLabsService = () => useServices().labs;
@ -52,7 +50,6 @@ export const LegacyServicesProvider: FC<{
const value = {
embeddables: specifiedProviders.embeddables.getService(),
expressions: specifiedProviders.expressions.getService(),
notify: specifiedProviders.notify.getService(),
platform: specifiedProviders.platform.getService(),
navLink: specifiedProviders.navLink.getService(),
search: specifiedProviders.search.getService(),

View file

@ -8,7 +8,6 @@
import { BehaviorSubject } from 'rxjs';
import { CoreSetup, CoreStart, AppUpdater } from '../../../../../../src/core/public';
import { CanvasSetupDeps, CanvasStartDeps } from '../../plugin';
import { notifyServiceFactory } from './notify';
import { platformServiceFactory } from './platform';
import { navLinkServiceFactory } from './nav_link';
import { embeddablesServiceFactory } from './embeddables';
@ -17,7 +16,6 @@ import { searchServiceFactory } from './search';
import { labsServiceFactory } from './labs';
import { reportingServiceFactory } from './reporting';
export { NotifyService } from './notify';
export { SearchService } from './search';
export { PlatformService } from './platform';
export { NavLinkService } from './nav_link';
@ -79,7 +77,6 @@ export type ServiceFromProvider<P> = P extends CanvasServiceProvider<infer T> ?
export const services = {
embeddables: new CanvasServiceProvider(embeddablesServiceFactory),
expressions: new CanvasServiceProvider(expressionsServiceFactory),
notify: new CanvasServiceProvider(notifyServiceFactory),
platform: new CanvasServiceProvider(platformServiceFactory),
navLink: new CanvasServiceProvider(navLinkServiceFactory),
search: new CanvasServiceProvider(searchServiceFactory),
@ -92,7 +89,6 @@ export type CanvasServiceProviders = typeof services;
export interface CanvasServices {
embeddables: ServiceFromProvider<typeof services.embeddables>;
expressions: ServiceFromProvider<typeof services.expressions>;
notify: ServiceFromProvider<typeof services.notify>;
platform: ServiceFromProvider<typeof services.platform>;
navLink: ServiceFromProvider<typeof services.navLink>;
search: ServiceFromProvider<typeof services.search>;
@ -120,7 +116,6 @@ export const stopServices = () => {
export const {
embeddables: embeddableService,
notify: notifyService,
platform: platformService,
navLink: navLinkService,
expressions: expressionsService,

View file

@ -10,7 +10,6 @@ import { embeddablesService } from './embeddables';
import { expressionsService } from './expressions';
import { reportingService } from './reporting';
import { navLinkService } from './nav_link';
import { notifyService } from './notify';
import { labsService } from './labs';
import { platformService } from './platform';
import { searchService } from './search';
@ -20,7 +19,6 @@ export const stubs: CanvasServices = {
expressions: expressionsService,
reporting: reportingService,
navLink: navLinkService,
notify: notifyService,
platform: platformService,
search: searchService,
labs: labsService,

View file

@ -0,0 +1,15 @@
/*
* 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 { ToastInputFields } from '../../../../../src/core/public';
export interface CanvasNotifyService {
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;
}

View file

@ -13,6 +13,7 @@ import {
import { CanvasPluginServices } from '..';
import { pluginServiceProviders as stubProviders } from '../stubs';
import { workpadServiceFactory } from './workpad';
import { notifyServiceFactory } from './notify';
export interface StorybookParams {
hasTemplates?: boolean;
@ -26,6 +27,7 @@ export const pluginServiceProviders: PluginServiceProviders<
> = {
...stubProviders,
workpad: new PluginServiceProvider(workpadServiceFactory),
notify: new PluginServiceProvider(notifyServiceFactory),
};
export const argTypes = {

View file

@ -0,0 +1,22 @@
/*
* 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 { action } from '@storybook/addon-actions';
import { PluginServiceFactory } from '../../../../../../src/plugins/presentation_util/public';
import { StorybookParams } from '.';
import { CanvasNotifyService } from '../notify';
type CanvasNotifyServiceFactory = PluginServiceFactory<CanvasNotifyService, StorybookParams>;
export const notifyServiceFactory: CanvasNotifyServiceFactory = () => ({
success: (message) => action(`success: ${message}`)(),
error: (message) => action(`error: ${message}`)(),
info: (message) => action(`info: ${message}`)(),
warning: (message) => action(`warning: ${message}`)(),
});

View file

@ -15,11 +15,14 @@ import {
import { CanvasPluginServices } from '..';
import { workpadServiceFactory } from './workpad';
import { notifyServiceFactory } from './notify';
export { workpadServiceFactory } from './workpad';
export { notifyServiceFactory } from './notify';
export const pluginServiceProviders: PluginServiceProviders<CanvasPluginServices> = {
workpad: new PluginServiceProvider(workpadServiceFactory),
notify: new PluginServiceProvider(notifyServiceFactory),
};
export const pluginServiceRegistry = new PluginServiceRegistry<CanvasPluginServices>(

View file

@ -5,13 +5,17 @@
* 2.0.
*/
import { NotifyService } from '../notify';
import { PluginServiceFactory } from '../../../../../../src/plugins/presentation_util/public';
import { CanvasNotifyService } from '../notify';
type CanvasNotifyServiceFactory = PluginServiceFactory<CanvasNotifyService>;
const noop = (..._args: any[]): any => {};
export const notifyService: NotifyService = {
export const notifyServiceFactory: CanvasNotifyServiceFactory = () => ({
error: noop,
info: noop,
success: noop,
warning: noop,
};
});

View file

@ -17,7 +17,6 @@ export interface WorkpadFindResponse {
export interface TemplateFindResponse {
templates: CanvasTemplate[];
}
export interface CanvasWorkpadService {
get: (id: string) => Promise<CanvasWorkpad>;
create: (workpad: CanvasWorkpad) => Promise<CanvasWorkpad>;

View file

@ -22,7 +22,7 @@ import { getDefaultElement } from '../defaults';
import { ErrorStrings } from '../../../i18n';
import { runInterpreter, interpretAst } from '../../lib/run_interpreter';
import { subMultitree } from '../../lib/aeroelastic/functional';
import { services } from '../../services';
import { pluginServices } from '../../services';
import { selectToplevelNodes } from './transient';
import * as args from './resolved_args';
@ -144,7 +144,8 @@ const fetchRenderableWithContextFn = ({ dispatch, getState }, element, ast, cont
dispatch(getAction(renderable));
})
.catch((err) => {
services.notify.getService().error(err);
const notifyService = pluginServices.getServices().notify;
notifyService.error(err);
dispatch(getAction(err));
});
};
@ -188,7 +189,8 @@ export const fetchAllRenderables = createThunk(
return runInterpreter(ast, null, variables, { castToRender: true })
.then((renderable) => ({ path: argumentPath, value: renderable }))
.catch((err) => {
services.notify.getService().error(err);
const notifyService = pluginServices.getServices().notify;
notifyService.error(err);
return { path: argumentPath, value: err };
});
});
@ -307,7 +309,8 @@ const setAst = createThunk('setAst', ({ dispatch }, ast, element, pageId, doRend
const expression = toExpression(ast);
dispatch(setExpression(expression, element.id, pageId, doRender));
} catch (err) {
services.notify.getService().error(err);
const notifyService = pluginServices.getServices().notify;
notifyService.error(err);
// TODO: remove this, may have been added just to cause a re-render, but why?
dispatch(setExpression(element.expression, element.id, pageId, doRender));

View file

@ -15,7 +15,7 @@ import { setAssets, resetAssets } from '../actions/assets';
import * as transientActions from '../actions/transient';
import * as resolvedArgsActions from '../actions/resolved_args';
import { update, updateAssets, updateWorkpad } from '../../lib/workpad_service';
import { services } from '../../services';
import { pluginServices } from '../../services';
import { canUserWrite } from '../selectors/app';
const { esPersist: strings } = ErrorStrings;
@ -61,17 +61,19 @@ export const esPersistMiddleware = ({ getState }) => {
const notifyError = (err) => {
const statusCode = err.response && err.response.status;
const notifyService = pluginServices.getServices().notify;
switch (statusCode) {
case 400:
return services.notify.getService().error(err.response, {
return notifyService.error(err.response, {
title: strings.getSaveFailureTitle(),
});
case 413:
return services.notify.getService().error(strings.getTooLargeErrorMessage(), {
return notifyService.error(strings.getTooLargeErrorMessage(), {
title: strings.getSaveFailureTitle(),
});
default:
return services.notify.getService().error(err, {
return notifyService.error(err, {
title: strings.getUpdateFailureTitle(),
});
}

View file

@ -5,7 +5,6 @@
* 2.0.
*/
import { action } from '@storybook/addon-actions';
import { addParameters } from '@storybook/react';
import { startServices } from '../public/services/stubs';
@ -14,14 +13,7 @@ import { addDecorators } from './decorators';
// Import Canvas CSS
import '../public/style/index.scss';
startServices({
notify: {
success: (message) => action(`success: ${message}`)(),
error: (message) => action(`error: ${message}`)(),
info: (message) => action(`info: ${message}`)(),
warning: (message) => action(`warning: ${message}`)(),
},
});
startServices();
addDecorators();
addParameters({