mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Merge pull request #167 from dbeaver/feature/expired-session-snackbar
Feature/expired session snackbar
This commit is contained in:
@@ -21,6 +21,7 @@ export * from './shared/NavigationTabs/NavigationTabsService';
|
||||
export * from './shared/NavigationTabs/TabNavigationContext';
|
||||
export * from './shared/ToolsPanel/LogViewTab/LogViewerMenuService';
|
||||
export * from './shared/ToolsPanel/LogViewTab/LogViewerService';
|
||||
export * from './shared/SessionExpire/SessionExpireService';
|
||||
export * from './NavigationTree/NavigationTreeService';
|
||||
export * from './NavigationTree/NavigationTreeContextMenuService';
|
||||
export * from './AppLocaleService';
|
||||
|
||||
+13
-3
@@ -8,12 +8,14 @@
|
||||
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import { ActionSnackbar } from '@cloudbeaver/core-blocks';
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogService } from '@cloudbeaver/core-dialogs';
|
||||
import { ENotificationType, NotificationService } from '@cloudbeaver/core-events';
|
||||
import {
|
||||
GQLError, GraphQLService, EServerErrorCode
|
||||
} from '@cloudbeaver/core-sdk';
|
||||
|
||||
import { CommonDialogService } from '../CommonDialog/CommonDialogService';
|
||||
import { SessionExpiredDialog } from './SessionExpiredDialog';
|
||||
|
||||
@injectable()
|
||||
@@ -23,11 +25,12 @@ export class SessionExpireService {
|
||||
onSessionExpire = new Subject();
|
||||
constructor(
|
||||
private graphQLService: GraphQLService,
|
||||
private notificationService: NotificationService,
|
||||
private commonDialogService: CommonDialogService
|
||||
) {
|
||||
}
|
||||
|
||||
subscribe() {
|
||||
subscribe(): void {
|
||||
this.graphQLService.registerInterceptor(this.sessionExpiredInterceptor.bind(this));
|
||||
}
|
||||
|
||||
@@ -40,7 +43,14 @@ export class SessionExpireService {
|
||||
&& !this.isNotifiedAboutExpiredSession) {
|
||||
this.isNotifiedAboutExpiredSession = true;
|
||||
this.onSessionExpire.next();
|
||||
await this.commonDialogService.open(SessionExpiredDialog, null);
|
||||
try {
|
||||
await this.commonDialogService.open(SessionExpiredDialog, null);
|
||||
} finally {
|
||||
this.notificationService.customNotification(() => ActionSnackbar, {
|
||||
actionText: 'app_root_session_expired_reload',
|
||||
onAction: () => location.reload(),
|
||||
}, { title: 'app_root_session_expired_title', persistent: true, type: ENotificationType.Error });
|
||||
}
|
||||
}
|
||||
throw exception;
|
||||
}
|
||||
+1
-3
@@ -11,12 +11,10 @@ import { useCallback } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { Button } from '@cloudbeaver/core-blocks';
|
||||
import { CommonDialogWrapper, DialogComponentProps } from '@cloudbeaver/core-dialogs';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { CommonDialogWrapper } from '../CommonDialog/CommonDialog/CommonDialogWrapper';
|
||||
import { DialogComponentProps } from '../CommonDialog/CommonDialogService';
|
||||
|
||||
const styles = css`
|
||||
dialog-content {
|
||||
display: flex;
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 { useEffect, useState } from 'react';
|
||||
import styled, { use } from 'reshadow';
|
||||
|
||||
import { Button, IconButton } from '@cloudbeaver/core-blocks';
|
||||
import { NotificationComponentProps } from '@cloudbeaver/core-events';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { NotificationMark } from '@cloudbeaver/core-notifications';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { SNACKBAR_COMMON_STYLES } from './SnackbarCommonStyles';
|
||||
|
||||
type ExtraProps = {
|
||||
onAction: () => void;
|
||||
actionText: string;
|
||||
}
|
||||
|
||||
export const ActionSnackbar: React.FC<NotificationComponentProps & ExtraProps> = function ActionSnackbar({
|
||||
notification, onAction, actionText,
|
||||
}) {
|
||||
const styles = useStyles(SNACKBAR_COMMON_STYLES);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const translate = useTranslate();
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
return styled(styles)(
|
||||
<notification as="div" {...use({ mounted })}>
|
||||
<notification-header as="div">
|
||||
<NotificationMark type={notification.type} />
|
||||
<message as="div">{translate(notification.title)}</message>
|
||||
{!notification.persistent && (
|
||||
<IconButton
|
||||
name="cross"
|
||||
viewBox="0 0 16 16"
|
||||
onClick={notification.close}
|
||||
/>
|
||||
)}
|
||||
</notification-header>
|
||||
<notification-body as="div">
|
||||
<actions as="div">
|
||||
<Button type="button" mod={['outlined']} onClick={onAction}>
|
||||
{translate(actionText)}
|
||||
</Button>
|
||||
</actions>
|
||||
</notification-body>
|
||||
</notification>
|
||||
);
|
||||
};
|
||||
+1
-1
@@ -10,7 +10,7 @@ import { css } from 'reshadow';
|
||||
|
||||
import { composes } from '@cloudbeaver/core-theming';
|
||||
|
||||
export const SNACKBAR_STYLES = composes(
|
||||
export const SNACKBAR_COMMON_STYLES = composes(
|
||||
css`
|
||||
notification {
|
||||
composes: theme-background-surface theme-text-on-surface from global;
|
||||
@@ -33,3 +33,5 @@ export * from './TextPlaceholder';
|
||||
export * from './useClipboard';
|
||||
export * from './useFocus';
|
||||
export * from './BlocksLocaleService';
|
||||
export * from './Snackbars/ActionSnackbar';
|
||||
export * from './Snackbars/SnackbarCommonStyles';
|
||||
|
||||
@@ -11,10 +11,9 @@ import {
|
||||
NavigationTabsService,
|
||||
NavigationTreeContextMenuService,
|
||||
LogViewerMenuService,
|
||||
ConnectionSchemaManagerService,
|
||||
ConnectionSchemaManagerService, SessionExpireService
|
||||
} from '@cloudbeaver/core-app';
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { SessionExpireService } from '@cloudbeaver/core-dialogs';
|
||||
import { ExceptionsCatcherService } from '@cloudbeaver/core-events';
|
||||
import { ThemeService } from '@cloudbeaver/core-theming';
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
CoreSettingsService,
|
||||
AdministrationTopAppBarBootstrapService,
|
||||
AppLocaleService,
|
||||
SessionExpireService
|
||||
} from '@cloudbeaver/core-app';
|
||||
import {
|
||||
AuthInfoService,
|
||||
@@ -61,7 +62,7 @@ import {
|
||||
ConnectionsAdministrationNavService,
|
||||
} from '@cloudbeaver/core-connections';
|
||||
import { PluginManifest } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogService, ContextMenuService, SessionExpireService } from '@cloudbeaver/core-dialogs';
|
||||
import { CommonDialogService, ContextMenuService } from '@cloudbeaver/core-dialogs';
|
||||
import { NotificationService, ExceptionsCatcherService, EventsSettingsService } from '@cloudbeaver/core-events';
|
||||
import { LocalizationService } from '@cloudbeaver/core-localization';
|
||||
import { PluginManagerService } from '@cloudbeaver/core-plugin';
|
||||
|
||||
@@ -14,5 +14,3 @@ export * from './Menu/models/ComputedMenuPanelModel';
|
||||
export * from './Menu/ContextMenu/ContextMenuService';
|
||||
export * from './Menu/ContextMenu/IContextMenuItem';
|
||||
export * from './Menu/ContextMenu/IMenuContext';
|
||||
|
||||
export * from './SessionExpire/SessionExpireService';
|
||||
|
||||
@@ -11,6 +11,8 @@ import { PluginManagerService } from '@cloudbeaver/core-plugin';
|
||||
|
||||
const defaultSettings = {
|
||||
notificationsPool: 5,
|
||||
maxPersistentAllow: 1,
|
||||
|
||||
};
|
||||
|
||||
export type EventsSettings = typeof defaultSettings
|
||||
|
||||
@@ -9,34 +9,50 @@
|
||||
export enum ENotificationType {
|
||||
Info = 'Info',
|
||||
Error = 'Error',
|
||||
Success = 'Success',
|
||||
Custom =' Custom'
|
||||
}
|
||||
|
||||
export type NotificationComponentProps<T = undefined> = {
|
||||
notification: INotification<T>;
|
||||
export type INotificationExtraProps<T> = Record<string, any> & {
|
||||
source?: T;
|
||||
}
|
||||
|
||||
export type NotificationComponentProps<
|
||||
TSource = undefined,
|
||||
TProps extends INotificationExtraProps<TSource> = INotificationExtraProps<TSource>> = {
|
||||
notification: INotification<TSource, TProps>;
|
||||
onClose: () => void;
|
||||
}
|
||||
export type NotificationComponent<T = undefined> = React.FunctionComponent<NotificationComponentProps<T>>
|
||||
|
||||
export interface INotification<T = undefined> {
|
||||
export type NotificationComponent<
|
||||
TSource = undefined,
|
||||
TProps extends INotificationExtraProps<TSource> = INotificationExtraProps<TSource>,
|
||||
> = React.FunctionComponent<NotificationComponentProps<TSource> & TProps>
|
||||
|
||||
export interface INotification<
|
||||
TSource = undefined,
|
||||
TProps extends INotificationExtraProps<TSource> = INotificationExtraProps<TSource>> {
|
||||
readonly id: number;
|
||||
type: ENotificationType;
|
||||
title: string;
|
||||
message?: string;
|
||||
details?: string | Error;
|
||||
persistent?: boolean;
|
||||
isSilent: boolean;
|
||||
customComponent?: () => NotificationComponent<T>;
|
||||
source: T;
|
||||
extraProps: TProps;
|
||||
customComponent?: () => NotificationComponent<TSource, TProps>;
|
||||
close: () => void;
|
||||
showDetails: () => void;
|
||||
}
|
||||
|
||||
export interface INotificationOptions<T = undefined> {
|
||||
export interface INotificationOptions<
|
||||
TSource = undefined,
|
||||
TProps extends INotificationExtraProps<TSource> = INotificationExtraProps<TSource>> {
|
||||
title: string;
|
||||
message?: string;
|
||||
details?: string | Error;
|
||||
isSilent?: boolean;
|
||||
persistent?: boolean;
|
||||
customComponent?: () => NotificationComponent<T>;
|
||||
source?: T;
|
||||
extraProps?: TProps;
|
||||
customComponent?: () => NotificationComponent<TSource, TProps>;
|
||||
}
|
||||
|
||||
@@ -12,51 +12,70 @@ import { OrderedMap } from '@cloudbeaver/core-utils';
|
||||
|
||||
import { EventsSettingsService } from './EventsSettingsService';
|
||||
import {
|
||||
ENotificationType, INotification, INotificationOptions, NotificationComponent
|
||||
ENotificationType, INotification, INotificationExtraProps, INotificationOptions, NotificationComponent
|
||||
} from './INotification';
|
||||
|
||||
@injectable()
|
||||
export class NotificationService {
|
||||
readonly notificationList = new OrderedMap<number, INotification<any>>(({ id }) => id);
|
||||
// todo change to common new Map()
|
||||
readonly notificationList = new OrderedMap<number, INotification<any, any>>(({ id }) => id);
|
||||
private notificationNextId = 0
|
||||
|
||||
constructor(
|
||||
private settings: EventsSettingsService,
|
||||
) {}
|
||||
|
||||
notify<T = never>(options: INotificationOptions<T>, type: ENotificationType) {
|
||||
notify<TSource = never, TProps extends INotificationExtraProps<
|
||||
TSource> = Record<string, any>>(
|
||||
options: INotificationOptions<TSource, TProps>, type: ENotificationType
|
||||
) {
|
||||
if (options.persistent) {
|
||||
const persistentNotifications = this.notificationList.values.filter(value => value.persistent);
|
||||
if (persistentNotifications.length >= this.settings.settings.getValue('maxPersistentAllow')) {
|
||||
throw new Error(`You cannot create more than ${this.settings.settings.getValue('maxPersistentAllow')} persistent notification`);
|
||||
}
|
||||
}
|
||||
|
||||
const id = this.notificationNextId++;
|
||||
|
||||
const notification: INotification<T> = {
|
||||
const notification: INotification<TSource, TProps> = {
|
||||
id,
|
||||
title: options.title,
|
||||
message: options.message,
|
||||
details: options.details,
|
||||
isSilent: !!options.isSilent,
|
||||
customComponent: options.customComponent,
|
||||
source: options.source!,
|
||||
extraProps: options.extraProps || {} as TProps,
|
||||
persistent: options.persistent,
|
||||
type,
|
||||
close: this.close.bind(this, id),
|
||||
showDetails: this.showDetails.bind(this, id),
|
||||
};
|
||||
|
||||
this.notificationList.addValue(notification);
|
||||
|
||||
if (this.notificationList.values.length > this.settings.settings.getValue('notificationsPool')) {
|
||||
this.notificationList.remove(this.notificationList.keys[0]);
|
||||
const filteredNotificationList = this.notificationList.values.filter(notification => !notification.persistent);
|
||||
|
||||
if (filteredNotificationList.length > this.settings.settings.getValue('notificationsPool')) {
|
||||
let i = 0;
|
||||
while (this.notificationList.get(this.notificationList.keys[i])?.persistent) {
|
||||
i++;
|
||||
}
|
||||
this.notificationList.remove(this.notificationList.keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
customNotification<T = never>(
|
||||
component: () => NotificationComponent<T>,
|
||||
source?: T,
|
||||
options?: INotificationOptions<T>
|
||||
customNotification<TSource = never, TProps extends INotificationExtraProps<TSource> = Record<string, any>>(
|
||||
component: () => NotificationComponent<TSource, TProps>,
|
||||
props?: TProps & INotificationExtraProps<TSource>,
|
||||
options?: INotificationOptions<TSource, TProps> & { type?: ENotificationType; }
|
||||
) {
|
||||
this.notify({
|
||||
title: '',
|
||||
...options,
|
||||
customComponent: component,
|
||||
source,
|
||||
}, ENotificationType.Custom);
|
||||
extraProps: props || {} as TProps,
|
||||
}, options?.type ?? ENotificationType.Custom);
|
||||
}
|
||||
|
||||
logInfo<T>(notification: INotificationOptions<T>) {
|
||||
|
||||
@@ -18,7 +18,7 @@ export const defaultRULocale = [
|
||||
['ui_data_saving_error', 'Ошибка при сохранении изменений'],
|
||||
['ui_no_matches_placeholder', 'По вашему запросу ничего не найдено.'],
|
||||
['root_permission_denied', 'Отказано в доступе'],
|
||||
['app_root_session_expired_title', 'Сесстия истекла'],
|
||||
['app_root_session_expired_title', 'Сессия истекла'],
|
||||
['app_root_session_expired_message', 'Сессия истекла. Хотите перезагрузить страницу?'],
|
||||
['app_root_session_expired_reload', 'Перезагрузить'],
|
||||
['core_eventsLog_dbeaverErrorDetails', 'Детали ошибки'],
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ export class NotificationItemController implements IInitializableController {
|
||||
this.handleShowDetails = this.showDetails.bind(this);
|
||||
}
|
||||
|
||||
if (notification.type !== ENotificationType.Error) {
|
||||
if (notification.type !== ENotificationType.Error && !notification.persistent) {
|
||||
this.closeAfter = FadeTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export const NotificationsItem = observer(function Notification({ notification }
|
||||
|
||||
if (notification.customComponent) {
|
||||
const Custom = notification.customComponent();
|
||||
return <Custom notification={notification} onClose={controller.handleClose} />;
|
||||
return <Custom notification={notification} onClose={controller.handleClose} {...notification.extraProps} />;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -34,9 +34,9 @@ export const NotificationsItem = observer(function Notification({ notification }
|
||||
text={notification.title}
|
||||
type={notification.type}
|
||||
disableShowDetails={controller.isDetailsDialogOpen}
|
||||
closeAfter={controller.closeAfter}
|
||||
onClose={controller.handleClose}
|
||||
onShowDetails={controller.handleShowDetails}
|
||||
closeAfter={controller.closeAfter}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -18,8 +18,10 @@ type IconProps = HTMLProps<HTMLDivElement> & {
|
||||
export function NotificationMark({ type, ...props }: IconProps) {
|
||||
return (
|
||||
<div {...props}>
|
||||
{/* todo change to info icon */}
|
||||
{type === ENotificationType.Info && <CheckCircle />}
|
||||
{type === ENotificationType.Error && <Frown />}
|
||||
{type === ENotificationType.Success && <CheckCircle />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,13 +9,12 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import styled, { use } from 'reshadow';
|
||||
|
||||
import { Button, IconButton } from '@cloudbeaver/core-blocks';
|
||||
import { Button, IconButton, SNACKBAR_COMMON_STYLES } from '@cloudbeaver/core-blocks';
|
||||
import { ENotificationType } from '@cloudbeaver/core-events';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { NotificationMark } from './NotificationMark';
|
||||
import { SNACKBAR_STYLES } from './styles';
|
||||
|
||||
type SnackbarProps = {
|
||||
type?: ENotificationType;
|
||||
@@ -34,7 +33,7 @@ export function Snackbar({
|
||||
onClose,
|
||||
onShowDetails,
|
||||
}: SnackbarProps) {
|
||||
const styles = useStyles(SNACKBAR_STYLES);
|
||||
const styles = useStyles(SNACKBAR_COMMON_STYLES);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [closing, setClosing] = useState(false);
|
||||
const translate = useTranslate();
|
||||
@@ -60,12 +59,12 @@ export function Snackbar({
|
||||
}, []);
|
||||
|
||||
return styled(styles)(
|
||||
<notification as="div" {...use({ mounted, closing })} >
|
||||
<notification as="div" {...use({ mounted, closing })}>
|
||||
<notification-header as="div">
|
||||
{type && <NotificationMark type={type} />}
|
||||
<message as="div">{translate(text)}</message>
|
||||
{!closeAfter && onClose && (
|
||||
<IconButton onClick={onClose} name="cross" viewBox="0 0 16 16" />
|
||||
<IconButton name="cross" viewBox="0 0 16 16" onClick={onClose} />
|
||||
)}
|
||||
</notification-header>
|
||||
<notification-body as="div">
|
||||
@@ -74,8 +73,8 @@ export function Snackbar({
|
||||
<Button
|
||||
type="button"
|
||||
mod={['outlined']}
|
||||
onClick={onShowDetails}
|
||||
disabled={disableShowDetails}
|
||||
onClick={onShowDetails}
|
||||
>
|
||||
{translate('ui_errors_details')}
|
||||
</Button>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export * from './NotificationsItem/Snackbar/styles';
|
||||
export * from './NotificationsItem/Snackbar/NotificationMark';
|
||||
export * from './NotificationsItem/ErrorDetailsDialog/ErrorDetailsDialog';
|
||||
export * from './Notifications';
|
||||
export * from './NotificationsItem/Snackbar/NotificationMark';
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
import { ENotificationType, NotificationService } from '@cloudbeaver/core-events';
|
||||
import { DataTransferParameters } from '@cloudbeaver/core-sdk';
|
||||
|
||||
import { DataExportProcessService } from './DataExportProcessService';
|
||||
@@ -48,7 +48,7 @@ export class DataExportService {
|
||||
parameters
|
||||
);
|
||||
|
||||
this.notificationService.customNotification(() => ExportNotification, taskId);
|
||||
this.notificationService.customNotification(() => ExportNotification, { source: taskId });
|
||||
return taskId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,12 @@ import { observer } from 'mobx-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import styled, { use, css } from 'reshadow';
|
||||
|
||||
import { Button, Loader, IconButton } from '@cloudbeaver/core-blocks';
|
||||
import {
|
||||
Button, Loader, IconButton, SNACKBAR_COMMON_STYLES
|
||||
} from '@cloudbeaver/core-blocks';
|
||||
import { useController } from '@cloudbeaver/core-di';
|
||||
import { NotificationComponentProps } from '@cloudbeaver/core-events';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { SNACKBAR_STYLES } from '@cloudbeaver/core-notifications';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
import { EDeferredState } from '@cloudbeaver/core-utils';
|
||||
|
||||
@@ -50,13 +51,13 @@ export const ExportNotification = observer(function ExportNotification({
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
return styled(useStyles(SNACKBAR_STYLES, styles))(
|
||||
<notification as="div" {...use({ mounted })} >
|
||||
return styled(useStyles(SNACKBAR_COMMON_STYLES, styles))(
|
||||
<notification as="div" {...use({ mounted })}>
|
||||
<notification-header as="div">
|
||||
<Loader loading={controller.isPending} hideMessage />
|
||||
<message as="div">{translate(controller.status)}</message>
|
||||
{!controller.isPending && (
|
||||
<IconButton onClick={controller.delete} name="cross" viewBox="0 0 16 16" />
|
||||
<IconButton name="cross" viewBox="0 0 16 16" onClick={controller.delete} />
|
||||
)}
|
||||
</notification-header>
|
||||
<notification-body as="div">
|
||||
@@ -78,8 +79,8 @@ export const ExportNotification = observer(function ExportNotification({
|
||||
tag='a'
|
||||
href={controller.downloadUrl}
|
||||
mod={['unelevated']}
|
||||
onClick={controller.download}
|
||||
download
|
||||
onClick={controller.download}
|
||||
>
|
||||
{translate('data_transfer_notification_download')}
|
||||
</Button>
|
||||
@@ -89,8 +90,8 @@ export const ExportNotification = observer(function ExportNotification({
|
||||
<Button
|
||||
type="button"
|
||||
mod={['outlined']}
|
||||
onClick={controller.showDetails}
|
||||
disabled={controller.isDetailsDialogOpen}
|
||||
onClick={controller.showDetails}
|
||||
>
|
||||
{translate('ui_errors_details')}
|
||||
</Button>
|
||||
@@ -99,8 +100,8 @@ export const ExportNotification = observer(function ExportNotification({
|
||||
<Button
|
||||
type="button"
|
||||
mod={['outlined']}
|
||||
onClick={controller.cancel}
|
||||
disabled={controller.process?.getState() === EDeferredState.CANCELLING}
|
||||
onClick={controller.cancel}
|
||||
>
|
||||
{translate('ui_processing_cancel')}
|
||||
</Button>
|
||||
|
||||
+5
-5
@@ -35,7 +35,7 @@ export class ExportNotificationController implements IInitializableController {
|
||||
}
|
||||
|
||||
get task() {
|
||||
return this.dataExportProcessService.exportProcesses.get(this.notification.source);
|
||||
return this.dataExportProcessService.exportProcesses.get(this.notification?.extraProps?.source);
|
||||
}
|
||||
|
||||
get hasDetails() {
|
||||
@@ -69,7 +69,7 @@ export class ExportNotificationController implements IInitializableController {
|
||||
}
|
||||
|
||||
get downloadUrl() {
|
||||
return this.dataExportProcessService.downloadUrl(this.notification.source);
|
||||
return this.dataExportProcessService.downloadUrl(this.notification.extraProps.source);
|
||||
}
|
||||
|
||||
private notification!: INotification<any>;
|
||||
@@ -86,17 +86,17 @@ export class ExportNotificationController implements IInitializableController {
|
||||
}
|
||||
|
||||
delete = () => {
|
||||
this.dataExportProcessService.delete(this.notification.source);
|
||||
this.dataExportProcessService.delete(this.notification.extraProps.source);
|
||||
this.notification.close();
|
||||
}
|
||||
|
||||
download = () => {
|
||||
this.dataExportProcessService.download(this.notification.source);
|
||||
this.dataExportProcessService.download(this.notification.extraProps.source);
|
||||
this.notification.close();
|
||||
}
|
||||
|
||||
cancel = () => {
|
||||
this.dataExportProcessService.cancel(this.notification.source);
|
||||
this.dataExportProcessService.cancel(this.notification.extraProps.source);
|
||||
}
|
||||
|
||||
showDetails= async () => {
|
||||
|
||||
Reference in New Issue
Block a user