mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Cb 4178 te cloud storage improvements (#2532)
* CB-4178 chore: makes tree nodes names visible in react dev tools * CB-4178 adds validation for loading files in cloud storage * CB-4178 pr fixes * CB-4178 pr fixes * CB-4178 code cleanup * CB-4178 selectFiles can return empty array --------- Co-authored-by: Evgenia Bezborodova <139753579+EvgeniaBzzz@users.noreply.github.com>
This commit is contained in:
co-authored by
Evgenia Bezborodova
parent
433eaacd24
commit
9e3e4322a3
@@ -121,3 +121,5 @@ export const TreeNode = observer<Props, HTMLDivElement | null>(
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
TreeNode.displayName = 'TreeNode';
|
||||
|
||||
@@ -127,3 +127,5 @@ export const TreeNodeControl = observer<Props & React.HTMLAttributes<HTMLDivElem
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
TreeNodeControl.displayName = 'TreeNodeControl';
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
export function selectFiles(callback: (files: FileList | null) => any, multiple?: boolean): void {
|
||||
export function selectFiles(callback: (files: File[]) => any, multiple?: boolean): void {
|
||||
let removed = false;
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
@@ -16,7 +16,7 @@ export function selectFiles(callback: (files: FileList | null) => any, multiple?
|
||||
}
|
||||
|
||||
input.onchange = () => {
|
||||
callback(input.files);
|
||||
callback(input.files?.length ? Array.from(input.files) : []);
|
||||
removed = true;
|
||||
input.remove();
|
||||
};
|
||||
@@ -30,9 +30,12 @@ export function selectFiles(callback: (files: FileList | null) => any, multiple?
|
||||
|
||||
input.click();
|
||||
|
||||
setTimeout(() => {
|
||||
if (!removed) {
|
||||
input.remove();
|
||||
}
|
||||
}, 30 * 60 * 1000);
|
||||
setTimeout(
|
||||
() => {
|
||||
if (!removed) {
|
||||
input.remove();
|
||||
}
|
||||
},
|
||||
30 * 60 * 1000,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ export class DBDriverResource extends CachedMapResource<string, DBDriver, DBDriv
|
||||
return this.data;
|
||||
}
|
||||
|
||||
async addDriverLibraries(driverId: string, files: FileList) {
|
||||
async addDriverLibraries(driverId: string, files: File[]) {
|
||||
await this.graphQLService.sdk.uploadDriverLibrary(driverId, files);
|
||||
await this.refresh(driverId);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ export class CustomGraphQLClient extends GraphQLClient {
|
||||
|
||||
async uploadFiles<T = any, V extends Variables = Variables>(
|
||||
url: string,
|
||||
files: FileList,
|
||||
files: File[],
|
||||
query?: string,
|
||||
variables?: V,
|
||||
onUploadProgress?: (event: UploadProgressEvent) => void,
|
||||
@@ -122,7 +122,7 @@ export class CustomGraphQLClient extends GraphQLClient {
|
||||
|
||||
private async overrideFilesUpload<T, V extends Variables = Variables>(
|
||||
url: string,
|
||||
files: FileList | Blob,
|
||||
files: File[] | Blob,
|
||||
query?: string,
|
||||
variables?: V,
|
||||
onUploadProgress?: (event: UploadProgressEvent) => void,
|
||||
@@ -139,7 +139,7 @@ export class CustomGraphQLClient extends GraphQLClient {
|
||||
fileData: undefined as any,
|
||||
};
|
||||
|
||||
if (files instanceof FileList) {
|
||||
if (files instanceof Array) {
|
||||
data['files[]'] = files;
|
||||
} else {
|
||||
data.fileData = files;
|
||||
|
||||
@@ -10,12 +10,12 @@ import { GlobalConstants } from '@cloudbeaver/core-utils';
|
||||
import type { CustomGraphQLClient, UploadProgressEvent } from '../CustomGraphQLClient';
|
||||
|
||||
export interface IUploadDriverLibraryExtension {
|
||||
uploadDriverLibrary: (driverId: string, files: FileList, onUploadProgress?: (event: UploadProgressEvent) => void) => Promise<void>;
|
||||
uploadDriverLibrary: (driverId: string, files: File[], onUploadProgress?: (event: UploadProgressEvent) => void) => Promise<void>;
|
||||
}
|
||||
|
||||
export function uploadDriverLibraryExtension(client: CustomGraphQLClient): IUploadDriverLibraryExtension {
|
||||
return {
|
||||
uploadDriverLibrary(driverId: string, files: FileList, onUploadProgress?: (event: UploadProgressEvent) => void): Promise<void> {
|
||||
uploadDriverLibrary(driverId: string, files: File[], onUploadProgress?: (event: UploadProgressEvent) => void): Promise<void> {
|
||||
return client.uploadFiles(GlobalConstants.absoluteServiceUrl('drivers', 'library'), files, undefined, { driverId }, onUploadProgress);
|
||||
},
|
||||
};
|
||||
|
||||
+6
-9
@@ -8,19 +8,16 @@
|
||||
import { selectFiles } from '@cloudbeaver/core-browser';
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
import {
|
||||
createResultSetBlobValue,
|
||||
ResultSetDataContentAction,
|
||||
ResultSetDataKeysUtils,
|
||||
ResultSetEditAction,
|
||||
ResultSetFormatAction,
|
||||
} from '@cloudbeaver/plugin-data-viewer';
|
||||
import { createResultSetBlobValue, ResultSetDataContentAction, ResultSetEditAction, ResultSetFormatAction } from '@cloudbeaver/plugin-data-viewer';
|
||||
|
||||
import { DataGridContextMenuService } from './DataGridContextMenuService';
|
||||
|
||||
@injectable()
|
||||
export class DataGridContextMenuSaveContentService {
|
||||
constructor(private readonly dataGridContextMenuService: DataGridContextMenuService, private readonly notificationService: NotificationService) {}
|
||||
constructor(
|
||||
private readonly dataGridContextMenuService: DataGridContextMenuService,
|
||||
private readonly notificationService: NotificationService,
|
||||
) {}
|
||||
|
||||
register(): void {
|
||||
this.dataGridContextMenuService.add(this.dataGridContextMenuService.getMenuToken(), {
|
||||
@@ -60,7 +57,7 @@ export class DataGridContextMenuSaveContentService {
|
||||
onClick: async context => {
|
||||
selectFiles(files => {
|
||||
const edit = context.data.model.source.getAction(context.data.resultIndex, ResultSetEditAction);
|
||||
const file = files?.item(0) ?? undefined;
|
||||
const file = files?.[0] ?? undefined;
|
||||
if (file) {
|
||||
edit.set(context.data.key, createResultSetBlobValue(file));
|
||||
}
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ export const ImageValuePresentation: TabContainerPanelComponent<IDataValuePanelP
|
||||
},
|
||||
async upload() {
|
||||
selectFiles(files => {
|
||||
const file = files?.item(0) ?? undefined;
|
||||
const file = files?.[0] ?? undefined;
|
||||
if (file && this.selectedCell) {
|
||||
this.editAction.set(this.selectedCell, createResultSetBlobValue(file));
|
||||
}
|
||||
|
||||
+4
-2
@@ -96,15 +96,15 @@ export const NavigationNodeProjectControl: NavTreeControlComponent = observer<Na
|
||||
return (
|
||||
<TreeNodeControl
|
||||
ref={ref}
|
||||
className={s(styles, { treeNodeControl: true, outdated }, className)}
|
||||
onClick={handleClick}
|
||||
onContextMenu={handleContextMenuOpen}
|
||||
className={s(styles, { treeNodeControl: true, outdated, }, className)}
|
||||
>
|
||||
<TreeNodeName title={name} className={s(styles, { treeNodeName: true })}>
|
||||
<div className={s(styles, { nameBox: true })}>{name}</div>
|
||||
</TreeNodeName>
|
||||
{!dndPlaceholder && (
|
||||
<div onClick={handlePortalClick} className={s(styles, { portal: true })}>
|
||||
<div className={s(styles, { portal: true })} onClick={handlePortalClick}>
|
||||
<TreeNodeMenuLoader mouseContextMenu={mouseContextMenu} node={node} selected={selected} />
|
||||
</div>
|
||||
)}
|
||||
@@ -112,3 +112,5 @@ export const NavigationNodeProjectControl: NavTreeControlComponent = observer<Na
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
NavigationNodeProjectControl.displayName = 'NavigationNodeProjectControl';
|
||||
+2
@@ -84,3 +84,5 @@ export const ConnectionNavNodeControl: NavTreeControlComponent = observer<NavTre
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
ConnectionNavNodeControl.displayName = 'ConnectionNavNodeControl';
|
||||
|
||||
+2
@@ -158,3 +158,5 @@ export const NavigationNodeControl: NavTreeControlComponent = observer(
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
NavigationNodeControl.displayName = 'NavigationNodeControl';
|
||||
|
||||
+2
@@ -72,3 +72,5 @@ export const NavigationNodeNested = observer(
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
NavigationNodeNested.displayName = 'NavigationNodeNested';
|
||||
|
||||
+2
@@ -108,3 +108,5 @@ export const NavigationNodeControlRenderer = observer<Props, HTMLDivElement>(
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
NavigationNodeControlRenderer.displayName = 'NavigationNodeControlRenderer';
|
||||
|
||||
+2
@@ -79,3 +79,5 @@ export const NavigationNodeProjectControl: NavTreeControlComponent = observer<Na
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
NavigationNodeProjectControl.displayName = 'NavigationNodeProjectControl';
|
||||
|
||||
Reference in New Issue
Block a user