mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-24 11:35:54 +08:00
fix(core-blocks): CB-1054 data loaders flickering
This commit is contained in:
@@ -11,25 +11,35 @@ import { useState, useEffect } from 'react';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
|
||||
export interface ComplexLoaderProps<T> {
|
||||
interface IComplexLoaderData<T> {
|
||||
promise: Promise<T> | undefined;
|
||||
data: T | undefined;
|
||||
error: Error | undefined;
|
||||
loader: () => Promise<T>;
|
||||
}
|
||||
|
||||
export interface ComplexLoaderProps<T> {
|
||||
loader: IComplexLoaderData<T>;
|
||||
placeholder: React.ReactElement;
|
||||
keepLoading?: boolean;
|
||||
children: (content: T) => JSX.Element;
|
||||
}
|
||||
|
||||
export const ComplexLoader: React.FC<ComplexLoaderProps<any>> = function ComplexLoader(props) {
|
||||
const [content, setContent] = useState<unknown | null>(null);
|
||||
const [content, setContent] = useState<unknown | null>(props.loader.data);
|
||||
const notificationService = useService(NotificationService);
|
||||
|
||||
useEffect(() => {
|
||||
let unmounted = false;
|
||||
|
||||
if (!content) {
|
||||
props
|
||||
.loader
|
||||
.loader()
|
||||
.then(value => !unmounted && setContent(value))
|
||||
.catch(exception => !unmounted && notificationService.logException(exception, 'Can\'t load resource'));
|
||||
}
|
||||
|
||||
return () => {
|
||||
unmounted = true;
|
||||
};
|
||||
@@ -41,3 +51,35 @@ export const ComplexLoader: React.FC<ComplexLoaderProps<any>> = function Complex
|
||||
|
||||
return props.children(content);
|
||||
};
|
||||
|
||||
export function createComplexLoader<T>(loader: () => Promise<T>): IComplexLoaderData<T> {
|
||||
return {
|
||||
promise: undefined,
|
||||
data: undefined,
|
||||
error: undefined,
|
||||
async loader() {
|
||||
if (this.data !== undefined) {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
if (this.error) {
|
||||
throw this.error;
|
||||
}
|
||||
|
||||
if (this.promise) {
|
||||
return await this.promise;
|
||||
}
|
||||
|
||||
this.promise = loader();
|
||||
|
||||
try {
|
||||
this.data = await this.promise;
|
||||
return this.data;
|
||||
} catch (exception) {
|
||||
this.error = exception;
|
||||
|
||||
throw exception;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { ComplexLoader, Loader } from '@cloudbeaver/core-blocks';
|
||||
import { ComplexLoader, createComplexLoader, Loader } from '@cloudbeaver/core-blocks';
|
||||
|
||||
async function loader() {
|
||||
const loader = createComplexLoader(async function loader() {
|
||||
const { ReactSanitizedHTML } = await import('./ReactSanitizedHTML');
|
||||
return { ReactSanitizedHTML };
|
||||
}
|
||||
});
|
||||
|
||||
interface Props {
|
||||
html: string;
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { ComplexLoader, Loader } from '@cloudbeaver/core-blocks';
|
||||
import { ComplexLoader, createComplexLoader, Loader } from '@cloudbeaver/core-blocks';
|
||||
|
||||
import type { ICodeEditorProps } from './ICodeEditorProps';
|
||||
|
||||
async function loader() {
|
||||
const loader = createComplexLoader(async function loader() {
|
||||
const { CodeEditor } = await import('./CodeEditor');
|
||||
return { CodeEditor };
|
||||
}
|
||||
});
|
||||
|
||||
export const CodeEditorLoader: React.FC<ICodeEditorProps> = function CodeEditorLoader(props) {
|
||||
return (
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import { ComplexLoader, Loader } from '@cloudbeaver/core-blocks';
|
||||
import { ComplexLoader, createComplexLoader, Loader } from '@cloudbeaver/core-blocks';
|
||||
import type { IDatabaseDataModel } from '@cloudbeaver/plugin-data-viewer';
|
||||
|
||||
interface Props {
|
||||
@@ -17,10 +17,10 @@ interface Props {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
async function loader() {
|
||||
const loader = createComplexLoader(async function loader() {
|
||||
const { DataGridTable } = await import('./DataGridTable');
|
||||
return { DataGridTable };
|
||||
}
|
||||
});
|
||||
|
||||
export const DataGridLoader: React.FC<Props> = observer(function DataGridLoader({
|
||||
tableModel, resultIndex, className,
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import type { TabContainerPanelComponent } from '@cloudbeaver/core-blocks';
|
||||
import { createComplexLoader, TabContainerPanelComponent } from '@cloudbeaver/core-blocks';
|
||||
import { ComplexLoader, Loader } from '@cloudbeaver/core-blocks';
|
||||
import type { IDataValuePanelProps, IDatabaseResultSet } from '@cloudbeaver/plugin-data-viewer';
|
||||
|
||||
async function loader() {
|
||||
const loader = createComplexLoader(async function loader() {
|
||||
const { GISValuePresentation } = await import('./GISValuePresentation');
|
||||
return { GISValuePresentation };
|
||||
}
|
||||
});
|
||||
|
||||
export const GISViewer: TabContainerPanelComponent<IDataValuePanelProps<any, IDatabaseResultSet>> = function GISViewer({ model, resultIndex }) {
|
||||
return (
|
||||
|
||||
+3
-3
@@ -8,15 +8,15 @@
|
||||
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import { ComplexLoader, Loader } from '@cloudbeaver/core-blocks';
|
||||
import { ComplexLoader, createComplexLoader, Loader } from '@cloudbeaver/core-blocks';
|
||||
|
||||
import type { ISQLCodeEditorProps } from './ISQLCodeEditorProps';
|
||||
import type { SQLCodeEditorController } from './SQLCodeEditorController';
|
||||
|
||||
async function loader() {
|
||||
const loader = createComplexLoader(async function loader() {
|
||||
const { SQLCodeEditor } = await import('./SQLCodeEditor');
|
||||
return { SQLCodeEditor };
|
||||
}
|
||||
});
|
||||
|
||||
export const SQLCodeEditorLoader = observer<ISQLCodeEditorProps, SQLCodeEditorController>(function SQLCodeEditorLoader(props, ref) {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user