mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
152 lines
3.8 KiB
TypeScript
152 lines
3.8 KiB
TypeScript
/*
|
|
* CloudBeaver - Cloud Database Manager
|
|
* Copyright (C) 2020-2022 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 { observable } from 'mobx';
|
|
import { observer } from 'mobx-react-lite';
|
|
import styled, { css, use } from 'reshadow';
|
|
|
|
import { Button, IconOrImage, useErrorDetails, useObservableRef, useStateDelay } from '@cloudbeaver/core-blocks';
|
|
import { useTranslate } from '@cloudbeaver/core-localization';
|
|
import { ServerErrorType } from '@cloudbeaver/core-sdk';
|
|
import { useStyles } from '@cloudbeaver/core-theming';
|
|
|
|
import type { IDatabaseDataModel } from '../DatabaseDataModel/IDatabaseDataModel';
|
|
|
|
const style = css`
|
|
error {
|
|
composes: theme-background-surface theme-text-on-surface from global;
|
|
position: absolute;
|
|
box-sizing: border-box;
|
|
width: 100%;
|
|
height: 100%;
|
|
padding: 16px;
|
|
overflow: auto;
|
|
pointer-events: none;
|
|
bottom: 0;
|
|
right: 0;
|
|
z-index: 1;
|
|
opacity: 0;
|
|
transition: opacity 0.3s ease-in-out, width 0.3s ease-in-out, height 0.3s ease-in-out, background 0.3s ease-in-out;
|
|
|
|
&[|animated] {
|
|
overflow: hidden;
|
|
pointer-events: auto;
|
|
opacity: 1;
|
|
}
|
|
&[|collapsed] {
|
|
pointer-events: auto;
|
|
width: 92px;
|
|
height: 72px;
|
|
background: transparent!important;
|
|
|
|
& IconOrImage {
|
|
cursor: pointer;
|
|
}
|
|
|
|
& error-message, & controls {
|
|
display: none;
|
|
}
|
|
}
|
|
&[|errorHidden] {
|
|
pointer-events: none;
|
|
}
|
|
}
|
|
error-body {
|
|
display: flex;
|
|
gap: 24px;
|
|
align-items: center;
|
|
margin-bottom: 24px;
|
|
}
|
|
error-message {
|
|
white-space: pre-wrap;
|
|
}
|
|
IconOrImage {
|
|
width: 40px;
|
|
height: 40px;
|
|
}
|
|
controls {
|
|
display: flex;
|
|
gap: 16px;
|
|
& > Button {
|
|
flex-shrink: 0;
|
|
}
|
|
}
|
|
`;
|
|
|
|
interface Props {
|
|
model: IDatabaseDataModel;
|
|
loading: boolean;
|
|
className?: string;
|
|
}
|
|
|
|
interface ErrorInfo {
|
|
error: Error | null;
|
|
display: boolean;
|
|
hide: () => void;
|
|
show: () => void;
|
|
}
|
|
|
|
export const TableError = observer<Props>(function TableViewer({
|
|
model,
|
|
loading,
|
|
className,
|
|
}) {
|
|
const translate = useTranslate();
|
|
const errorInfo = useObservableRef<ErrorInfo>(() => ({
|
|
error: null,
|
|
display: false,
|
|
hide() {
|
|
this.display = false;
|
|
},
|
|
show() {
|
|
this.display = true;
|
|
},
|
|
}), {
|
|
display: observable.ref,
|
|
}, false);
|
|
|
|
if (errorInfo.error !== model.source.error) {
|
|
errorInfo.error = model.source.error || null;
|
|
errorInfo.display = !!model.source.error;
|
|
}
|
|
|
|
const error = useErrorDetails(model.source.error || null);
|
|
const animated = useStateDelay(!!errorInfo.error && !loading, 1);
|
|
|
|
const errorHidden = errorInfo.error === null;
|
|
const quote = error.details?.errorType === ServerErrorType.QUOTE_EXCEEDED;
|
|
|
|
let icon = '/icons/error_icon.svg';
|
|
|
|
if (quote) {
|
|
icon = '/icons/info_icon.svg';
|
|
}
|
|
|
|
return styled(useStyles(style))(
|
|
<error {...use({ animated, collapsed: !errorInfo.display, errorHidden })} className={className}>
|
|
<error-body>
|
|
<IconOrImage icon={icon} title={error.details?.message} onClick={() => errorInfo.show()} />
|
|
<error-message>{error.details?.message}</error-message>
|
|
</error-body>
|
|
<controls>
|
|
<Button type='button' mod={['outlined']} onClick={() => errorInfo.hide()}>
|
|
{translate('ui_error_close')}
|
|
</Button>
|
|
{error.details?.hasDetails && (
|
|
<Button type='button' mod={['outlined']} onClick={error.open}>
|
|
{translate('ui_errors_details')}
|
|
</Button>
|
|
)}
|
|
<Button type='button' mod={['unelevated']} onClick={() => model.retry()}>
|
|
{translate('ui_processing_retry')}
|
|
</Button>
|
|
</controls>
|
|
</error>
|
|
);
|
|
});
|