mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-24 11:35:54 +08:00
Cb 4112 open scripts datasets from virtual file systems (#2089)
* CB-4125 use base path * CB-4112 feat: read objectId * CB-4145 add required auth to fs system api * CB-4145 move feature * CB-4112 feat: open scripts from file systems * CB-4125 improve file reading * CB-4112 refactor: naming * CB-4112 update schema * CB-4112 fs by id gql * CB-4112 unique fs id * CB-4112 fix gql schema * CB-4112 fix gql schema * CB-4112 update manifest * CB-4112 feat: require authentication for nav-tree --------- Co-authored-by: Aleksey Potsetsuev <wrouds@gmail.com> Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
This commit is contained in:
co-authored by
Aleksey Potsetsuev
Daria Marutkina
parent
0f9e7b650c
commit
cb60358ae6
@@ -14,7 +14,7 @@ import { isResourceOfType, ProjectInfoResource, ProjectsService } from '@cloudbe
|
||||
import { CachedMapAllKey, CachedTreeChildrenKey } from '@cloudbeaver/core-resource';
|
||||
import { getRmResourcePath, NAV_NODE_TYPE_RM_RESOURCE, ResourceManagerResource, RESOURCES_NODE_PATH } from '@cloudbeaver/core-resource-manager';
|
||||
import { createPath, getPathName } from '@cloudbeaver/core-utils';
|
||||
import { ACTION_SAVE, ActionService, DATA_CONTEXT_MENU, KEY_BINDING_SAVE, KeyBindingService, MenuService } from '@cloudbeaver/core-view';
|
||||
import { ActionService, DATA_CONTEXT_MENU, MenuService } from '@cloudbeaver/core-view';
|
||||
import { NavigationTabsService } from '@cloudbeaver/plugin-navigation-tabs';
|
||||
import { getResourceKeyFromNodeId } from '@cloudbeaver/plugin-navigation-tree-rm';
|
||||
import { RESOURCE_NAME_REGEX, ResourceManagerService } from '@cloudbeaver/plugin-resource-manager';
|
||||
@@ -55,7 +55,6 @@ export class PluginBootstrap extends Bootstrap {
|
||||
private readonly sqlEditorSettingsService: SqlEditorSettingsService,
|
||||
private readonly resourceManagerResource: ResourceManagerResource,
|
||||
private readonly resourceManagerScriptsService: ResourceManagerScriptsService,
|
||||
private readonly keyBindingService: KeyBindingService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -83,10 +82,6 @@ export class PluginBootstrap extends Bootstrap {
|
||||
return dataSource instanceof MemorySqlDataSource || dataSource instanceof LocalStorageSqlDataSource;
|
||||
}
|
||||
|
||||
if (action === ACTION_SAVE) {
|
||||
return dataSource?.isAutoSaveEnabled === false;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
handler: async (context, action) => {
|
||||
@@ -187,34 +182,9 @@ export class PluginBootstrap extends Bootstrap {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (action === ACTION_SAVE) {
|
||||
const state = context.get(DATA_CONTEXT_SQL_EDITOR_STATE);
|
||||
const source = this.sqlDataSourceService.get(state.editorId) as ResourceSqlDataSource | undefined;
|
||||
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
await source.save();
|
||||
}
|
||||
},
|
||||
isDisabled: (context, action) => {
|
||||
if (action === ACTION_SAVE) {
|
||||
const state = context.get(DATA_CONTEXT_SQL_EDITOR_STATE);
|
||||
const source = this.sqlDataSourceService.get(state.editorId) as ResourceSqlDataSource | undefined;
|
||||
|
||||
if (!source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return source.isLoading() || source.isSaved;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
getActionInfo: (context, action) => {
|
||||
if (action === ACTION_SAVE_AS_SCRIPT || action === ACTION_SAVE) {
|
||||
if (action === ACTION_SAVE_AS_SCRIPT) {
|
||||
return {
|
||||
...action.info,
|
||||
label: '',
|
||||
@@ -241,23 +211,7 @@ export class PluginBootstrap extends Bootstrap {
|
||||
!!dataSource?.hasFeature(ESqlDataSourceFeatures.script)
|
||||
);
|
||||
},
|
||||
getItems: (context, items) => [...items, ACTION_SAVE_AS_SCRIPT, ACTION_SAVE],
|
||||
});
|
||||
|
||||
this.keyBindingService.addKeyBindingHandler({
|
||||
id: 'script-save',
|
||||
binding: KEY_BINDING_SAVE,
|
||||
isBindingApplicable: (context, action) => action === ACTION_SAVE,
|
||||
handler: async context => {
|
||||
const state = context.get(DATA_CONTEXT_SQL_EDITOR_STATE);
|
||||
const source = this.sqlDataSourceService.get(state.editorId) as ResourceSqlDataSource | undefined;
|
||||
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
await source.save();
|
||||
},
|
||||
getItems: (context, items) => [...items, ACTION_SAVE_AS_SCRIPT],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+20
-10
@@ -17,16 +17,13 @@ import { TaskScheduler } from '@cloudbeaver/core-executor';
|
||||
import type { ProjectInfoResource } from '@cloudbeaver/core-projects';
|
||||
import { isResourceAlias, ResourceKey, ResourceKeyUtils } from '@cloudbeaver/core-resource';
|
||||
import { getRmResourceKey, ResourceManagerResource } from '@cloudbeaver/core-resource-manager';
|
||||
import type { NetworkStateService } from '@cloudbeaver/core-root';
|
||||
import { debounce, getPathName, isArraysEqual, isNotNullDefined, isObjectsEqual, isValuesEqual } from '@cloudbeaver/core-utils';
|
||||
import { SCRIPTS_TYPE_ID } from '@cloudbeaver/plugin-resource-manager-scripts';
|
||||
import { BaseSqlDataSource, ESqlDataSourceFeatures, SqlEditorService } from '@cloudbeaver/plugin-sql-editor';
|
||||
|
||||
import type { IResourceSqlDataSourceState } from './IResourceSqlDataSourceState';
|
||||
|
||||
interface IResourceInfo {
|
||||
isReadonly?: (dataSource: ResourceSqlDataSource) => boolean;
|
||||
}
|
||||
|
||||
interface IResourceActions {
|
||||
rename(dataSource: ResourceSqlDataSource, key: string, name: string): Promise<string>;
|
||||
read(dataSource: ResourceSqlDataSource, key: string): Promise<string>;
|
||||
@@ -103,7 +100,6 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
}
|
||||
|
||||
private actions?: IResourceActions;
|
||||
private info?: IResourceInfo;
|
||||
private lastAction: (() => Promise<void>) | undefined;
|
||||
private state!: IResourceSqlDataSourceState;
|
||||
|
||||
@@ -112,6 +108,7 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
private resourceUseKeyId: string | null;
|
||||
|
||||
constructor(
|
||||
private readonly networkStateService: NetworkStateService,
|
||||
private readonly projectInfoResource: ProjectInfoResource,
|
||||
private readonly connectionInfoResource: ConnectionInfoResource,
|
||||
private readonly resourceManagerResource: ResourceManagerResource,
|
||||
@@ -144,10 +141,22 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
}
|
||||
|
||||
isReadonly(): boolean {
|
||||
return !this.isLoaded() || this.info?.isReadonly?.(this) === true;
|
||||
if (!this.projectId || !this.networkStateService.state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const project = this.projectInfoResource.get(this.projectId);
|
||||
|
||||
return !this.isLoaded() || !project?.canEditResources;
|
||||
}
|
||||
|
||||
isOutdated(): boolean {
|
||||
if (this.projectId) {
|
||||
if (this.projectInfoResource.isOutdated(this.projectId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return this.resourceKey !== undefined && super.isOutdated();
|
||||
}
|
||||
|
||||
@@ -189,10 +198,6 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
setInfo(info?: IResourceInfo): void {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
setName(name: string | null): void {
|
||||
name = name?.trim() ?? null;
|
||||
if (!name || name === this.name) {
|
||||
@@ -267,6 +272,11 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
if (this.state.resourceKey && !this.resourceUseKeyId) {
|
||||
this.resourceUseKeyId = this.resourceManagerResource.useTracker.use(this.state.resourceKey);
|
||||
}
|
||||
|
||||
if (this.projectId) {
|
||||
await this.projectInfoResource.load(this.projectId);
|
||||
}
|
||||
|
||||
await this.read();
|
||||
}
|
||||
|
||||
|
||||
+6
-39
@@ -5,7 +5,7 @@
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { action, makeObservable, observable, untracked } from 'mobx';
|
||||
import { action, makeObservable, observable } from 'mobx';
|
||||
|
||||
import { ConfirmationDialog } from '@cloudbeaver/core-blocks';
|
||||
import { ConnectionInfoResource, IConnectionExecutionContextInfo } from '@cloudbeaver/core-connections';
|
||||
@@ -13,11 +13,11 @@ import { Bootstrap, injectable } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dialogs';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
import { ProjectInfoResource } from '@cloudbeaver/core-projects';
|
||||
import { CachedMapAllKey, resourceKeyList, ResourceKeySimple, ResourceKeyUtils } from '@cloudbeaver/core-resource';
|
||||
import { getRmResourceKey, IResourceManagerMoveData, ResourceManagerResource } from '@cloudbeaver/core-resource-manager';
|
||||
import { NetworkStateService, WindowEventsService } from '@cloudbeaver/core-root';
|
||||
import { resourceKeyList, ResourceKeySimple, ResourceKeyUtils } from '@cloudbeaver/core-resource';
|
||||
import { IResourceManagerMoveData, ResourceManagerResource } from '@cloudbeaver/core-resource-manager';
|
||||
import { NetworkStateService } from '@cloudbeaver/core-root';
|
||||
import { LocalStorageSaveService } from '@cloudbeaver/core-settings';
|
||||
import { createPath, getPathParent, throttle } from '@cloudbeaver/core-utils';
|
||||
import { createPath, getPathParent } from '@cloudbeaver/core-utils';
|
||||
import { NavigationTabsService } from '@cloudbeaver/plugin-navigation-tabs';
|
||||
import { NavResourceNodeService } from '@cloudbeaver/plugin-navigation-tree-rm';
|
||||
import { ResourceManagerService } from '@cloudbeaver/plugin-resource-manager';
|
||||
@@ -30,7 +30,6 @@ import { ResourceSqlDataSource } from './ResourceSqlDataSource';
|
||||
import { SqlEditorTabResourceService } from './SqlEditorTabResourceService';
|
||||
|
||||
const RESOURCE_TAB_STATE = 'sql_editor_resource_tab_state';
|
||||
const SYNC_DELAY = 5 * 60 * 1000;
|
||||
|
||||
@injectable()
|
||||
export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
@@ -49,14 +48,12 @@ export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
private readonly resourceManagerResource: ResourceManagerResource,
|
||||
private readonly resourceManagerScriptsService: ResourceManagerScriptsService,
|
||||
private readonly projectInfoResource: ProjectInfoResource,
|
||||
private readonly windowEventsService: WindowEventsService,
|
||||
private readonly sqlEditorTabResourceService: SqlEditorTabResourceService,
|
||||
private readonly sqlEditorService: SqlEditorService,
|
||||
localStorageSaveService: LocalStorageSaveService,
|
||||
) {
|
||||
super();
|
||||
this.dataSourceStateState = new Map();
|
||||
this.focusChangeHandler = throttle(this.focusChangeHandler.bind(this), SYNC_DELAY, false);
|
||||
|
||||
makeObservable<this, 'dataSourceStateState' | 'createState'>(this, {
|
||||
createState: action,
|
||||
@@ -87,7 +84,6 @@ export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
}
|
||||
|
||||
register(): void | Promise<void> {
|
||||
this.windowEventsService.onFocusChange.addHandler(this.focusChangeHandler.bind(this));
|
||||
this.resourceManagerResource.onItemDelete.addHandler(this.resourceDeleteHandler.bind(this));
|
||||
this.resourceManagerResource.onMove.addHandler(this.resourceMoveHandler.bind(this));
|
||||
|
||||
@@ -95,6 +91,7 @@ export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
key: ResourceSqlDataSource.key,
|
||||
getDataSource: (editorId, options) => {
|
||||
const dataSource = new ResourceSqlDataSource(
|
||||
this.networkStateService,
|
||||
this.projectInfoResource,
|
||||
this.connectionInfoResource,
|
||||
this.resourceManagerResource,
|
||||
@@ -118,20 +115,6 @@ export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
setProperties: this.setProperties.bind(this),
|
||||
});
|
||||
|
||||
dataSource.setInfo({
|
||||
isReadonly: (dataSource: ResourceSqlDataSource) => {
|
||||
if (!dataSource.resourceKey) {
|
||||
return true;
|
||||
}
|
||||
const resourceKey = getRmResourceKey(dataSource.resourceKey);
|
||||
|
||||
untracked(() => this.projectInfoResource.load(CachedMapAllKey));
|
||||
const project = this.projectInfoResource.get(resourceKey.projectId);
|
||||
|
||||
return !this.networkStateService.state || !project?.canEditResources;
|
||||
},
|
||||
});
|
||||
|
||||
return dataSource;
|
||||
},
|
||||
onDestroy: (_, editorId) => this.deleteState(editorId),
|
||||
@@ -188,22 +171,6 @@ export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
this.dataSourceStateState.delete(editorId);
|
||||
}
|
||||
|
||||
private async focusChangeHandler(focused: boolean) {
|
||||
if (!this.resourceManagerService.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (focused) {
|
||||
const dataSources = this.sqlDataSourceService.dataSources
|
||||
.filter(([, dataSource]) => dataSource instanceof ResourceSqlDataSource)
|
||||
.map(([, dataSource]) => dataSource as ResourceSqlDataSource);
|
||||
|
||||
for (const dataSource of dataSources) {
|
||||
dataSource.markOutdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private resourceMoveHandler(data: IResourceManagerMoveData) {
|
||||
if (!this.resourceManagerService.enabled) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user