mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-12 23:37:00 +08:00
Merge pull request #212 from dbeaver/refactor/snackbar-reusable-component
refactor(core-blocks): CB-479 apply reusable snackbar components to a…
This commit is contained in:
+1
-1
@@ -37,7 +37,7 @@ export class SessionExpiredDialogService extends Bootstrap {
|
||||
this.notificationService.customNotification(() => ActionSnackbar, {
|
||||
actionText: 'app_root_session_expired_reload',
|
||||
onAction: () => location.reload(),
|
||||
}, { title: 'app_root_session_expired_title', persistent: true, type: ENotificationType.Info });
|
||||
}, { title: 'app_root_session_expired_title', persistent: true, type: ENotificationType.Error });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
*/
|
||||
|
||||
import { observer } from 'mobx-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import styled, { use } from 'reshadow';
|
||||
|
||||
import { Button, IconButton } from '@cloudbeaver/core-blocks';
|
||||
import { Button } from '@cloudbeaver/core-blocks';
|
||||
import { INotificationExtraProps, NotificationComponent } from '@cloudbeaver/core-events';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { NotificationMark } from './NotificationMark';
|
||||
import { SNACKBAR_COMMON_STYLES } from './SnackbarCommonStyles';
|
||||
import { SnackbarBody } from './SnackbarMarkups/SnackbarBody';
|
||||
import { SnackbarContent } from './SnackbarMarkups/SnackbarContent';
|
||||
import { SnackbarFooter } from './SnackbarMarkups/SnackbarFooter';
|
||||
import { SnackbarStatus } from './SnackbarMarkups/SnackbarStatus';
|
||||
import { SnackbarWrapper } from './SnackbarMarkups/SnackbarWrapper';
|
||||
|
||||
interface Props extends INotificationExtraProps {
|
||||
onAction: () => void;
|
||||
@@ -26,36 +26,21 @@ interface Props extends INotificationExtraProps {
|
||||
export const ActionSnackbar: NotificationComponent<Props> = observer(function ActionSnackbar({
|
||||
notification, onAction, actionText,
|
||||
}) {
|
||||
const styles = useStyles(SNACKBAR_COMMON_STYLES);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const translate = useTranslate();
|
||||
const timeStringFromTimestamp = notification.timestamp ? new Date(notification.timestamp).toLocaleTimeString() : '';
|
||||
const translatedTitle = translate(notification.title);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
return styled(styles)(
|
||||
<notification as="div" {...use({ mounted })}>
|
||||
<NotificationMark type={notification.type} />
|
||||
<notification-body as="div">
|
||||
<body-text-block as='div'>
|
||||
<text-block-title title={translatedTitle} as='h2'>{translatedTitle}</text-block-title>
|
||||
{notification.message && <message as="div">{translate(notification.message)}</message>}
|
||||
</body-text-block>
|
||||
<notification-footer as='div'>
|
||||
<footer-time as='span'>{timeStringFromTimestamp}</footer-time>
|
||||
<actions as="div">
|
||||
<Button type="button" mod={['outlined']} onClick={onAction}>
|
||||
{translate(actionText)}
|
||||
</Button>
|
||||
</actions>
|
||||
</notification-footer>
|
||||
</notification-body>
|
||||
{!notification.persistent && (
|
||||
<IconButton name="cross" viewBox="0 0 16 16" onClick={() => notification.close(false)} />
|
||||
)}
|
||||
</notification>
|
||||
return (
|
||||
<SnackbarWrapper unclosable={notification.persistent} onClose={() => notification.close(false)}>
|
||||
<SnackbarStatus status={notification.type} />
|
||||
<SnackbarContent>
|
||||
<SnackbarBody title={translate(notification.title)}>
|
||||
{notification.message && translate(notification.message)}
|
||||
</SnackbarBody>
|
||||
<SnackbarFooter timestamp={notification.timestamp}>
|
||||
<Button type="button" mod={['outlined']} onClick={onAction}>
|
||||
{translate(actionText)}
|
||||
</Button>
|
||||
</SnackbarFooter>
|
||||
</SnackbarContent>
|
||||
</SnackbarWrapper>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -19,7 +19,6 @@ import { SnackbarContent } from './SnackbarMarkups/SnackbarContent';
|
||||
import { SnackbarFooter } from './SnackbarMarkups/SnackbarFooter';
|
||||
import { SnackbarStatus } from './SnackbarMarkups/SnackbarStatus';
|
||||
import { SnackbarWrapper } from './SnackbarMarkups/SnackbarWrapper';
|
||||
|
||||
interface Props extends INotificationProcessExtraProps {
|
||||
closeDelay?: number;
|
||||
displayDelay?: number;
|
||||
@@ -46,12 +45,14 @@ export const ProcessSnackbar: NotificationComponent<Props> = observer(function P
|
||||
return (
|
||||
<SnackbarWrapper
|
||||
closing={!!notification.state.deleteDelay}
|
||||
closeable={status !== ENotificationType.Loading}
|
||||
unclosable={status === ENotificationType.Loading}
|
||||
onClose={() => notification.close(false)}
|
||||
>
|
||||
<SnackbarStatus status={status} />
|
||||
<SnackbarContent>
|
||||
<SnackbarBody title={translate(title)} message={message && translate(message)} />
|
||||
<SnackbarBody title={translate(title)}>
|
||||
{message && translate(message)}
|
||||
</SnackbarBody>
|
||||
<SnackbarFooter timestamp={notification.timestamp}>
|
||||
{error && (
|
||||
<Button
|
||||
|
||||
@@ -7,24 +7,25 @@
|
||||
*/
|
||||
|
||||
import { observer } from 'mobx-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import styled, { use } from 'reshadow';
|
||||
|
||||
import { Button, IconButton, SNACKBAR_COMMON_STYLES } from '@cloudbeaver/core-blocks';
|
||||
import { Button } from '@cloudbeaver/core-blocks';
|
||||
import { ENotificationType } from '@cloudbeaver/core-events';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { useStateDelay } from '../useStateDelay';
|
||||
import { NotificationMark } from './NotificationMark';
|
||||
import { SnackbarBody } from './SnackbarMarkups/SnackbarBody';
|
||||
import { SnackbarContent } from './SnackbarMarkups/SnackbarContent';
|
||||
import { SnackbarFooter } from './SnackbarMarkups/SnackbarFooter';
|
||||
import { SnackbarStatus } from './SnackbarMarkups/SnackbarStatus';
|
||||
import { SnackbarWrapper } from './SnackbarMarkups/SnackbarWrapper';
|
||||
|
||||
interface SnackbarProps {
|
||||
type?: ENotificationType;
|
||||
type: ENotificationType;
|
||||
message?: string;
|
||||
title: string;
|
||||
closeDelay: number;
|
||||
disableShowDetails?: boolean;
|
||||
time?: number;
|
||||
time: number;
|
||||
onClose: (delayDeleting?: boolean) => void;
|
||||
state?: { deleteDelay: number };
|
||||
onShowDetails?: () => void;
|
||||
@@ -41,42 +42,29 @@ export const Snackbar: React.FC<SnackbarProps> = observer(function Snackbar({
|
||||
state,
|
||||
time,
|
||||
}) {
|
||||
const styles = useStyles(SNACKBAR_COMMON_STYLES);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const translate = useTranslate();
|
||||
const timeStringFromTimestamp = time ? new Date(time).toLocaleTimeString() : '';
|
||||
const translatedTitle = translate(title);
|
||||
useStateDelay(closeDelay > 0, closeDelay, onClose);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
return styled(styles)(
|
||||
<notification as="div" {...use({ mounted, closing: !!state?.deleteDelay })}>
|
||||
{type && <NotificationMark type={type} />}
|
||||
<notification-body as="div">
|
||||
<body-text-block as='div'>
|
||||
<text-block-title title={translatedTitle} as='h2'>{translatedTitle}</text-block-title>
|
||||
{message && <message as="div">{translate(message)}</message>}
|
||||
</body-text-block>
|
||||
<notification-footer as='div'>
|
||||
<footer-time as='span'>{timeStringFromTimestamp}</footer-time>
|
||||
return (
|
||||
<SnackbarWrapper closing={!!state?.deleteDelay} onClose={() => onClose(false)}>
|
||||
<SnackbarStatus status={type} />
|
||||
<SnackbarContent>
|
||||
<SnackbarBody title={translate(title)}>
|
||||
{message && translate(message)}
|
||||
</SnackbarBody>
|
||||
<SnackbarFooter timestamp={time}>
|
||||
{onShowDetails && (
|
||||
<actions as="div">
|
||||
<Button
|
||||
type="button"
|
||||
mod={['outlined']}
|
||||
disabled={disableShowDetails}
|
||||
onClick={onShowDetails}
|
||||
>
|
||||
{translate('ui_errors_details')}
|
||||
</Button>
|
||||
</actions>
|
||||
<Button
|
||||
type="button"
|
||||
mod={['outlined']}
|
||||
disabled={disableShowDetails}
|
||||
onClick={onShowDetails}
|
||||
>
|
||||
{translate('ui_errors_details')}
|
||||
</Button>
|
||||
)}
|
||||
</notification-footer>
|
||||
</notification-body>
|
||||
<IconButton name="cross" viewBox="0 0 16 16" onClick={() => onClose(false)} />
|
||||
</notification>
|
||||
</SnackbarFooter>
|
||||
</SnackbarContent>
|
||||
</SnackbarWrapper>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* cloudbeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { css } from 'reshadow';
|
||||
|
||||
import { composes } from '@cloudbeaver/core-theming';
|
||||
|
||||
export const SNACKBAR_COMMON_STYLES = composes(
|
||||
css`
|
||||
notification {
|
||||
composes: theme-background-surface theme-text-on-surface from global;
|
||||
}
|
||||
`,
|
||||
css`
|
||||
notification {
|
||||
composes: theme-elevation-z5 from global;
|
||||
position: relative;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
width: 500px;
|
||||
margin-bottom: 16px;
|
||||
margin-left: 16px;
|
||||
padding: 16px 16px;
|
||||
line-height: 1.5;
|
||||
opacity: 0;
|
||||
border-radius: 4px;
|
||||
transition: opacity 0.3s ease-in-out, transform 0.5s ease-in-out;
|
||||
transform: translateX(-100%);
|
||||
|
||||
&[use|mounted] {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
&[use|closing] {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
notification-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 0 0;
|
||||
& body-text-block {
|
||||
margin-top: 8px;
|
||||
padding-right: 24px;
|
||||
& message {
|
||||
font-size: 16px;
|
||||
opacity: 0.8;
|
||||
overflow: auto;
|
||||
max-height: 200px;
|
||||
margin-bottom: 8px;
|
||||
word-break: break-word;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
text-block-title {
|
||||
composes: theme-typography--headline6 from global;
|
||||
max-width: 392px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
line-height: 1.55rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
notification-footer {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
footer-time {
|
||||
composes: theme-typography--caption from global;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
NotificationMark {
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
actions {
|
||||
display: flex;
|
||||
& Button {
|
||||
margin-left: 16px;
|
||||
&:first-child {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
IconButton {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
`
|
||||
);
|
||||
@@ -43,16 +43,19 @@ const SNACKBAR_BODY_STYLES = css`
|
||||
|
||||
interface ISnackbarBodyProps {
|
||||
title: string;
|
||||
message: string | null;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const SnackbarBody: React.FC<ISnackbarBodyProps> = function SnackbarBody({ title, message, className }) {
|
||||
export const SnackbarBody: React.FC<ISnackbarBodyProps> = function SnackbarBody({
|
||||
title, className, children,
|
||||
}) {
|
||||
return styled(SNACKBAR_BODY_STYLES)(
|
||||
<notification-body as="div" className={className}>
|
||||
<body-text-block as='div'>
|
||||
<text-block-title title={title} as='h2'>{title}</text-block-title>
|
||||
{message && <message as="div">{message}</message>}
|
||||
<message as="div">
|
||||
{children}
|
||||
</message>
|
||||
</body-text-block>
|
||||
</notification-body>
|
||||
);
|
||||
|
||||
@@ -21,6 +21,11 @@ const SNACKBAR_FOOTER_STYLES = css`
|
||||
actions:empty {
|
||||
display: none;
|
||||
}
|
||||
actions:not(:empty) {
|
||||
& > *:not(:first-child) {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
interface ISnackbarFooter {
|
||||
|
||||
@@ -56,14 +56,14 @@ const SNACKBAR_WRAPPER_STYLES = composes(
|
||||
);
|
||||
|
||||
interface ISnackbarWrapperProps {
|
||||
closing: boolean;
|
||||
closeable: boolean;
|
||||
closing?: boolean;
|
||||
unclosable?: boolean;
|
||||
onClose?: () => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const SnackbarWrapper: React.FC<ISnackbarWrapperProps> = function SnackbarWrapper({
|
||||
closing, closeable, onClose, children, className,
|
||||
closing = false, unclosable, onClose, children, className,
|
||||
}) {
|
||||
const styles = useStyles(SNACKBAR_WRAPPER_STYLES);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
@@ -75,7 +75,7 @@ export const SnackbarWrapper: React.FC<ISnackbarWrapperProps> = function Snackba
|
||||
return styled(styles)(
|
||||
<notification as="div" className={className} {...use({ mounted, closing })}>
|
||||
{children}
|
||||
{closeable && onClose && (
|
||||
{!unclosable && onClose && (
|
||||
<IconButton name="cross" viewBox="0 0 16 16" onClick={onClose} />
|
||||
)}
|
||||
</notification>
|
||||
|
||||
@@ -52,7 +52,11 @@ export * from './useErrorDetails';
|
||||
export * from './useAppLoadingScreen';
|
||||
export * from './BlocksLocaleService';
|
||||
export * from './Snackbars/NotificationMark';
|
||||
export * from './Snackbars/SnackbarMarkups/SnackbarWrapper';
|
||||
export * from './Snackbars/SnackbarMarkups/SnackbarStatus';
|
||||
export * from './Snackbars/SnackbarMarkups/SnackbarContent';
|
||||
export * from './Snackbars/SnackbarMarkups/SnackbarBody';
|
||||
export * from './Snackbars/SnackbarMarkups/SnackbarFooter';
|
||||
export * from './Snackbars/Snackbar';
|
||||
export * from './Snackbars/ActionSnackbar';
|
||||
export * from './Snackbars/ProcessSnackbar';
|
||||
export * from './Snackbars/SnackbarCommonStyles';
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import { Snackbar } from '@cloudbeaver/core-blocks';
|
||||
import { useController } from '@cloudbeaver/core-di';
|
||||
import { INotification } from '@cloudbeaver/core-events';
|
||||
@@ -16,7 +18,7 @@ interface Props {
|
||||
notification: INotification<any>;
|
||||
}
|
||||
|
||||
export const NotificationsItem: React.FC<Props> = function Notification({ notification }) {
|
||||
export const NotificationsItem: React.FC<Props> = observer(function Notification({ notification }) {
|
||||
const controller = useController(NotificationItemController, notification);
|
||||
|
||||
if (notification.customComponent) {
|
||||
@@ -37,4 +39,4 @@ export const NotificationsItem: React.FC<Props> = function Notification({ notifi
|
||||
onShowDetails={controller.handleShowDetails}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -7,11 +7,10 @@
|
||||
*/
|
||||
|
||||
import { observer } from 'mobx-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import styled, { use, css } from 'reshadow';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import {
|
||||
Button, Loader, IconButton, SNACKBAR_COMMON_STYLES, NotificationMark
|
||||
Button, SnackbarWrapper, SnackbarStatus, SnackbarContent, SnackbarBody, SnackbarFooter
|
||||
} from '@cloudbeaver/core-blocks';
|
||||
import { useController } from '@cloudbeaver/core-di';
|
||||
import { ENotificationType, NotificationComponentProps } from '@cloudbeaver/core-events';
|
||||
@@ -22,9 +21,6 @@ import { EDeferredState } from '@cloudbeaver/core-utils';
|
||||
import { ExportNotificationController } from './ExportNotificationController';
|
||||
|
||||
const styles = css`
|
||||
Loader {
|
||||
margin-right: 16px;
|
||||
}
|
||||
source-name {
|
||||
composes: theme-typography--body2 from global;
|
||||
padding-top: 16px;
|
||||
@@ -35,12 +31,6 @@ const styles = css`
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
loader-container {
|
||||
& Loader {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
type Props = NotificationComponentProps<{
|
||||
@@ -52,84 +42,64 @@ export const ExportNotification: React.FC<Props> = observer(function ExportNotif
|
||||
}) {
|
||||
const controller = useController(ExportNotificationController, notification);
|
||||
const translate = useTranslate();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const timeStringFromTimestamp = notification.timestamp ? new Date(notification.timestamp).toLocaleTimeString() : '';
|
||||
const exportNotificationType = controller.isSuccess ? ENotificationType.Info : ENotificationType.Error;
|
||||
const translatedStatus = translate(controller.status);
|
||||
const { title, status } = controller.status;
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
return styled(useStyles(SNACKBAR_COMMON_STYLES, styles))(
|
||||
<notification as="div" {...use({ mounted })}>
|
||||
{!controller.isPending && <NotificationMark type={exportNotificationType} />}
|
||||
{controller.isPending && (
|
||||
<loader-container as='div'>
|
||||
<Loader fullSize hideMessage />
|
||||
</loader-container>
|
||||
)}
|
||||
<notification-body as="div">
|
||||
<body-text-block as='div'>
|
||||
<text-block-title title={translatedStatus} as="h2">{translatedStatus}</text-block-title>
|
||||
<message as="div">
|
||||
{controller.sourceName}
|
||||
{controller.task?.context.sourceName && (
|
||||
<pre title={controller.task?.context.sourceName}>
|
||||
{controller.task?.context.sourceName}
|
||||
</pre>
|
||||
)}
|
||||
</message>
|
||||
</body-text-block>
|
||||
<notification-footer as='div'>
|
||||
<footer-time as='span'>{timeStringFromTimestamp}</footer-time>
|
||||
<actions as="div">
|
||||
{controller.isSuccess && (
|
||||
<>
|
||||
<Button
|
||||
type="button"
|
||||
mod={['outlined']}
|
||||
onClick={controller.delete}
|
||||
>
|
||||
{translate('data_transfer_notification_delete')}
|
||||
</Button>
|
||||
<Button
|
||||
tag='a'
|
||||
href={controller.downloadUrl}
|
||||
mod={['unelevated']}
|
||||
download
|
||||
onClick={controller.download}
|
||||
>
|
||||
{translate('data_transfer_notification_download')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{controller.hasDetails && (
|
||||
return styled(useStyles(styles))(
|
||||
<SnackbarWrapper unclosable={status === ENotificationType.Loading} onClose={controller.delete}>
|
||||
<SnackbarStatus status={status} />
|
||||
<SnackbarContent>
|
||||
<SnackbarBody title={translate(title)}>
|
||||
{controller.sourceName}
|
||||
{controller.task?.context.sourceName && (
|
||||
<pre title={controller.task?.context.sourceName}>
|
||||
{controller.task?.context.sourceName}
|
||||
</pre>
|
||||
)}
|
||||
</SnackbarBody>
|
||||
<SnackbarFooter timestamp={notification.timestamp}>
|
||||
{status === ENotificationType.Info && (
|
||||
<>
|
||||
<Button
|
||||
type="button"
|
||||
mod={['outlined']}
|
||||
disabled={controller.isDetailsDialogOpen}
|
||||
onClick={controller.showDetails}
|
||||
onClick={controller.delete}
|
||||
>
|
||||
{translate('ui_errors_details')}
|
||||
{translate('data_transfer_notification_delete')}
|
||||
</Button>
|
||||
)}
|
||||
{controller.isPending && (
|
||||
<Button
|
||||
type="button"
|
||||
mod={['outlined']}
|
||||
disabled={controller.process?.getState() === EDeferredState.CANCELLING}
|
||||
onClick={controller.cancel}
|
||||
tag='a'
|
||||
href={controller.downloadUrl}
|
||||
mod={['unelevated']}
|
||||
download
|
||||
onClick={controller.download}
|
||||
>
|
||||
{translate('ui_processing_cancel')}
|
||||
{translate('data_transfer_notification_download')}
|
||||
</Button>
|
||||
)}
|
||||
</actions>
|
||||
</notification-footer>
|
||||
</notification-body>
|
||||
{!controller.isPending && (
|
||||
<IconButton name="cross" viewBox="0 0 16 16" onClick={controller.delete} />
|
||||
)}
|
||||
</notification>
|
||||
</>
|
||||
)}
|
||||
{status === ENotificationType.Error && (
|
||||
<Button
|
||||
type="button"
|
||||
mod={['outlined']}
|
||||
disabled={controller.isDetailsDialogOpen}
|
||||
onClick={controller.showDetails}
|
||||
>
|
||||
{translate('ui_errors_details')}
|
||||
</Button>
|
||||
)}
|
||||
{status === ENotificationType.Loading && (
|
||||
<Button
|
||||
type="button"
|
||||
mod={['outlined']}
|
||||
disabled={controller.process?.getState() === EDeferredState.CANCELLING}
|
||||
onClick={controller.cancel}
|
||||
>
|
||||
{translate('ui_processing_cancel')}
|
||||
</Button>
|
||||
)}
|
||||
</SnackbarFooter>
|
||||
</SnackbarContent>
|
||||
</SnackbarWrapper>
|
||||
|
||||
);
|
||||
});
|
||||
|
||||
+12
-8
@@ -11,13 +11,17 @@ import { observable, computed } from 'mobx';
|
||||
import { NavNodeManagerService } from '@cloudbeaver/core-app';
|
||||
import { IInitializableController, injectable } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogService } from '@cloudbeaver/core-dialogs';
|
||||
import { INotification } from '@cloudbeaver/core-events';
|
||||
import { ENotificationType, INotification } from '@cloudbeaver/core-events';
|
||||
import { LocalizationService } from '@cloudbeaver/core-localization';
|
||||
import { ErrorDetailsDialog } from '@cloudbeaver/core-notifications';
|
||||
import { Deferred, EDeferredState } from '@cloudbeaver/core-utils';
|
||||
|
||||
import { DataExportProcessService, ExportProcess } from '../DataExportProcessService';
|
||||
|
||||
interface ExportNotificationStatus {
|
||||
title: string;
|
||||
status: ENotificationType;
|
||||
}
|
||||
@injectable()
|
||||
export class ExportNotificationController implements IInitializableController {
|
||||
@observable isDetailsDialogOpen = false;
|
||||
@@ -55,16 +59,16 @@ export class ExportNotificationController implements IInitializableController {
|
||||
return this.localization.translate('data_transfer_exporting_sql');
|
||||
}
|
||||
|
||||
get status(): string {
|
||||
get status(): ExportNotificationStatus {
|
||||
switch (this.process?.getState()) {
|
||||
case EDeferredState.PENDING:
|
||||
return 'data_transfer_notification_preparation';
|
||||
return { title: 'data_transfer_notification_preparation', status: ENotificationType.Loading };
|
||||
case EDeferredState.CANCELLING:
|
||||
return 'ui_processing_canceling';
|
||||
return { title: 'ui_processing_canceling', status: ENotificationType.Loading };
|
||||
case EDeferredState.RESOLVED:
|
||||
return 'data_transfer_notification_ready';
|
||||
return { title: 'data_transfer_notification_ready', status: ENotificationType.Info };
|
||||
default:
|
||||
return 'data_transfer_notification_error';
|
||||
return { title: 'data_transfer_notification_error', status: ENotificationType.Error };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,12 +91,12 @@ export class ExportNotificationController implements IInitializableController {
|
||||
|
||||
delete = (): void => {
|
||||
this.dataExportProcessService.delete(this.notification.extraProps.source);
|
||||
this.notification.close();
|
||||
this.notification.close(false);
|
||||
};
|
||||
|
||||
download = (): void => {
|
||||
this.dataExportProcessService.download(this.notification.extraProps.source);
|
||||
this.notification.close();
|
||||
this.notification.close(false);
|
||||
};
|
||||
|
||||
cancel = (): void => {
|
||||
|
||||
Reference in New Issue
Block a user