mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-24 11:35:54 +08:00
Feat CB-3030 conflict resolving (#1814)
* CB-3030 feat: conflict resolving * CB-3030 fix: display os specific key instead of mod * CB-3030 fix: sql editor status * CB-3030 fix: styles and data validation * CB-3030 fix: sql editor styles --------- Co-authored-by: dariamarutkina <125263541+dariamarutkina@users.noreply.github.com>
This commit is contained in:
+5
@@ -6,8 +6,13 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import type { IConnectionExecutionContextInfo } from '@cloudbeaver/core-connections';
|
||||
import type { ISqlDataSourceHistoryState } from '@cloudbeaver/plugin-sql-editor';
|
||||
|
||||
export interface IResourceSqlDataSourceState {
|
||||
resourceKey?: string;
|
||||
script: string;
|
||||
baseScript: string;
|
||||
executionContext?: IConnectionExecutionContextInfo;
|
||||
baseExecutionContext?: IConnectionExecutionContextInfo;
|
||||
history: ISqlDataSourceHistoryState;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import { CachedMapAllKey } from '@cloudbeaver/core-sdk';
|
||||
import { createPath, getPathName } from '@cloudbeaver/core-utils';
|
||||
import { ACTION_SAVE, ActionService, DATA_CONTEXT_MENU, KEY_BINDING_SAVE, KeyBindingService, MenuService } from '@cloudbeaver/core-view';
|
||||
import { NavigationTabsService } from '@cloudbeaver/plugin-navigation-tabs';
|
||||
import { getResourceKeyFromNodeId, NavResourceNodeService } from '@cloudbeaver/plugin-navigation-tree-rm';
|
||||
import { getResourceKeyFromNodeId } from '@cloudbeaver/plugin-navigation-tree-rm';
|
||||
import { ResourceManagerService } from '@cloudbeaver/plugin-resource-manager';
|
||||
import { ResourceManagerScriptsService, SaveScriptDialog, SCRIPTS_TYPE_ID } from '@cloudbeaver/plugin-resource-manager-scripts';
|
||||
import {
|
||||
@@ -28,7 +28,6 @@ import {
|
||||
MemorySqlDataSource,
|
||||
SQL_EDITOR_TOOLS_MENU,
|
||||
SqlDataSourceService,
|
||||
SqlEditorService,
|
||||
SqlEditorSettingsService,
|
||||
} from '@cloudbeaver/plugin-sql-editor';
|
||||
import { isSQLEditorTab, SqlEditorNavigatorService } from '@cloudbeaver/plugin-sql-editor-navigation-tab';
|
||||
@@ -41,7 +40,6 @@ import { SqlEditorTabResourceService } from './SqlEditorTabResourceService';
|
||||
export class PluginBootstrap extends Bootstrap {
|
||||
constructor(
|
||||
private readonly navNodeManagerService: NavNodeManagerService,
|
||||
private readonly navResourceNodeService: NavResourceNodeService,
|
||||
private readonly navNodeInfoResource: NavNodeInfoResource,
|
||||
private readonly navigationTabsService: NavigationTabsService,
|
||||
private readonly notificationService: NotificationService,
|
||||
@@ -55,7 +53,6 @@ export class PluginBootstrap extends Bootstrap {
|
||||
private readonly menuService: MenuService,
|
||||
private readonly sqlDataSourceService: SqlDataSourceService,
|
||||
private readonly sqlEditorSettingsService: SqlEditorSettingsService,
|
||||
private readonly sqlEditorService: SqlEditorService,
|
||||
private readonly resourceManagerResource: ResourceManagerResource,
|
||||
private readonly resourceManagerScriptsService: ResourceManagerScriptsService,
|
||||
private readonly keyBindingService: KeyBindingService,
|
||||
@@ -70,33 +67,24 @@ export class PluginBootstrap extends Bootstrap {
|
||||
this.actionService.addHandler({
|
||||
id: 'scripts-base-handler',
|
||||
isActionApplicable: (context, action): boolean => {
|
||||
if (action === ACTION_SAVE_AS_SCRIPT || action === ACTION_SAVE) {
|
||||
const state = context.tryGet(DATA_CONTEXT_SQL_EDITOR_STATE);
|
||||
const state = context.tryGet(DATA_CONTEXT_SQL_EDITOR_STATE);
|
||||
|
||||
if (!state) {
|
||||
return false;
|
||||
}
|
||||
if (!state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.projectsService.activeProjects.some(project => project.canEditResources)) {
|
||||
return false;
|
||||
}
|
||||
if (!this.projectsService.activeProjects.some(project => project.canEditResources)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const dataSource = this.sqlDataSourceService.get(state.editorId);
|
||||
const dataSource = this.sqlDataSourceService.get(state.editorId);
|
||||
|
||||
if (action === ACTION_SAVE_AS_SCRIPT) {
|
||||
return dataSource instanceof MemorySqlDataSource || dataSource instanceof LocalStorageSqlDataSource;
|
||||
}
|
||||
|
||||
if (action === ACTION_SAVE) {
|
||||
return dataSource instanceof ResourceSqlDataSource;
|
||||
}
|
||||
if (action === ACTION_SAVE_AS_SCRIPT) {
|
||||
return dataSource instanceof MemorySqlDataSource || dataSource instanceof LocalStorageSqlDataSource;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
isHidden: (context, action) => {
|
||||
if (action === ACTION_SAVE) {
|
||||
return this.sqlEditorService.autoSave;
|
||||
return dataSource?.isAutoSaveEnabled === false;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -196,7 +184,7 @@ export class PluginBootstrap extends Bootstrap {
|
||||
return true;
|
||||
}
|
||||
|
||||
return source.isLoading() || source.isSaved();
|
||||
return source.isLoading() || source.isSaved;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
+205
-156
@@ -17,7 +17,7 @@ import { TaskScheduler } from '@cloudbeaver/core-executor';
|
||||
import type { ProjectInfoResource } from '@cloudbeaver/core-projects';
|
||||
import { getRmResourceKey, ResourceManagerResource } from '@cloudbeaver/core-resource-manager';
|
||||
import { isResourceAlias, ResourceKey, ResourceKeyUtils } from '@cloudbeaver/core-sdk';
|
||||
import { createPath, debounce, getPathName, getPathParent, isArraysEqual, isObjectsEqual, isValuesEqual } from '@cloudbeaver/core-utils';
|
||||
import { debounce, getPathName, isArraysEqual, 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';
|
||||
|
||||
@@ -28,7 +28,7 @@ interface IResourceInfo {
|
||||
}
|
||||
|
||||
interface IResourceActions {
|
||||
rename(dataSource: ResourceSqlDataSource, key: string, newKey: string): Promise<string>;
|
||||
rename(dataSource: ResourceSqlDataSource, key: string, name: string): Promise<string>;
|
||||
read(dataSource: ResourceSqlDataSource, key: string): Promise<string>;
|
||||
write(dataSource: ResourceSqlDataSource, key: string, value: string): Promise<void>;
|
||||
getProperties(dataSource: ResourceSqlDataSource, key: string): Promise<IConnectionExecutionContextInfo | undefined>;
|
||||
@@ -55,7 +55,15 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
}
|
||||
|
||||
get script(): string {
|
||||
return this._script;
|
||||
return this.state.script;
|
||||
}
|
||||
|
||||
get baseScript(): string {
|
||||
return this.state.baseScript;
|
||||
}
|
||||
|
||||
get baseExecutionContext(): IConnectionExecutionContextInfo | undefined {
|
||||
return this.state.baseExecutionContext;
|
||||
}
|
||||
|
||||
get projectId(): string | null {
|
||||
@@ -92,11 +100,14 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
return [ESqlDataSourceFeatures.script, ESqlDataSourceFeatures.query, ESqlDataSourceFeatures.executable, ESqlDataSourceFeatures.setName];
|
||||
}
|
||||
|
||||
private _script: string;
|
||||
get isAutoSaveEnabled(): boolean {
|
||||
return this.sqlEditorService.autoSave;
|
||||
}
|
||||
|
||||
private actions?: IResourceActions;
|
||||
private info?: IResourceInfo;
|
||||
private lastAction: (() => Promise<void>) | undefined;
|
||||
private readonly state: IResourceSqlDataSourceState;
|
||||
private state!: IResourceSqlDataSourceState;
|
||||
|
||||
private loaded: boolean;
|
||||
private readonly scheduler: TaskScheduler;
|
||||
@@ -110,8 +121,7 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
state: IResourceSqlDataSourceState,
|
||||
) {
|
||||
super();
|
||||
this.state = state;
|
||||
this._script = '';
|
||||
this.bindState(state);
|
||||
this.lastAction = undefined;
|
||||
this.loaded = false;
|
||||
this.resourceUseKeyId = null;
|
||||
@@ -122,18 +132,15 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
|
||||
resourceManagerResource.onDataOutdated.addHandler(this.syncResource);
|
||||
|
||||
makeObservable<this, '_script' | 'lastAction' | 'loaded'>(this, {
|
||||
makeObservable<this, 'lastAction' | 'loaded'>(this, {
|
||||
script: computed,
|
||||
executionContext: computed,
|
||||
resourceKey: computed,
|
||||
features: computed<ESqlDataSourceFeatures[]>({
|
||||
equals: isArraysEqual,
|
||||
}),
|
||||
_script: observable,
|
||||
lastAction: observable.ref,
|
||||
loaded: observable,
|
||||
setExecutionContext: action,
|
||||
setScript: action,
|
||||
setResourceKey: action,
|
||||
});
|
||||
}
|
||||
@@ -154,6 +161,20 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
return this.scheduler.executing;
|
||||
}
|
||||
|
||||
canRename(name: string | null): boolean {
|
||||
if (this.isReadonly()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
name = name.trim();
|
||||
|
||||
return !!this.actions && !!this.resourceKey && name.length > 0;
|
||||
}
|
||||
|
||||
setResourceKey(resourceKey: string | undefined): void {
|
||||
if (this.state.resourceKey && this.resourceUseKeyId) {
|
||||
this.resourceManagerResource.free(toJS(this.state.resourceKey), this.resourceUseKeyId);
|
||||
@@ -161,7 +182,8 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
}
|
||||
|
||||
this.state.resourceKey = toJS(resourceKey);
|
||||
this.reloadResource();
|
||||
this.loaded = false;
|
||||
this.markOutdated();
|
||||
this.onUpdate.execute();
|
||||
}
|
||||
|
||||
@@ -174,78 +196,45 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
}
|
||||
|
||||
setName(name: string | null): void {
|
||||
this.rename(name);
|
||||
name = name?.trim() ?? null;
|
||||
if (!name || name === this.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
const previousName = this.name;
|
||||
super.setName(name);
|
||||
|
||||
this.rename(name).catch(() => {
|
||||
super.setName(previousName);
|
||||
});
|
||||
}
|
||||
|
||||
setProject(projectId: string | null): void {
|
||||
super.setProject(projectId);
|
||||
}
|
||||
|
||||
canRename(name: string | null): boolean {
|
||||
if (this.isReadonly()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
name = name.trim();
|
||||
|
||||
return !!this.actions && !!this.resourceKey && this.saved && name.length > 0;
|
||||
}
|
||||
|
||||
setScript(script: string): void {
|
||||
const previous = this._script;
|
||||
const previous = this.state.script;
|
||||
if (previous === script) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._script = script;
|
||||
this.state.script = script;
|
||||
super.setScript(script);
|
||||
|
||||
if (this.sqlEditorService.autoSave && previous !== script) {
|
||||
if (this.isAutoSaveEnabled) {
|
||||
this.debouncedWrite();
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
this.resourceManagerResource.onItemUpdate.removeHandler(this.syncResource);
|
||||
if (this.state.resourceKey && this.resourceUseKeyId) {
|
||||
this.resourceManagerResource.free(this.state.resourceKey, this.resourceUseKeyId);
|
||||
this.resourceUseKeyId = null;
|
||||
}
|
||||
}
|
||||
setExecutionContext(executionContext: IConnectionExecutionContextInfo | undefined): void {
|
||||
executionContext = JSON.parse(JSON.stringify(toJS(executionContext) ?? {}));
|
||||
|
||||
syncResource(key: ResourceKey<string>) {
|
||||
if (isResourceAlias(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resourceKey = this.resourceKey;
|
||||
if (resourceKey && ResourceKeyUtils.some(key, key => resourceKey.startsWith(key))) {
|
||||
this.reloadResource();
|
||||
}
|
||||
}
|
||||
|
||||
reloadResource(): void {
|
||||
this.markOutdated();
|
||||
this.saved = true;
|
||||
this.loaded = false;
|
||||
}
|
||||
|
||||
async load(): Promise<void> {
|
||||
if (this.state.resourceKey && !this.resourceUseKeyId) {
|
||||
this.resourceUseKeyId = this.resourceManagerResource.use(this.state.resourceKey);
|
||||
}
|
||||
await this.read();
|
||||
}
|
||||
|
||||
setExecutionContext(executionContext?: IConnectionExecutionContextInfo): void {
|
||||
if (this.resourceKey && executionContext?.projectId && getRmResourceKey(this.resourceKey).projectId !== executionContext.projectId) {
|
||||
throw new Error('Resource SQL Data Source and Execution context projects don\t match');
|
||||
}
|
||||
|
||||
if (!isObjectsEqual(toJS(this.state.executionContext), toJS(executionContext))) {
|
||||
if (!isObjectsEqual(toJS(this.state.executionContext), executionContext)) {
|
||||
const initNew =
|
||||
!isValuesEqual(executionContext?.connectionId, this.executionContext?.connectionId, undefined) ||
|
||||
!isValuesEqual(executionContext?.defaultCatalog, this.executionContext?.defaultCatalog, undefined) ||
|
||||
@@ -263,130 +252,182 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
}
|
||||
}
|
||||
|
||||
this.state.executionContext = toJS(executionContext);
|
||||
this.state.executionContext = executionContext;
|
||||
super.setExecutionContext(executionContext);
|
||||
|
||||
if (this.sqlEditorService.autoSave) {
|
||||
if (this.isAutoSaveEnabled) {
|
||||
this.debouncedSaveProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async rename(name: string | null) {
|
||||
await this.write();
|
||||
|
||||
await this.scheduler.schedule(undefined, async () => {
|
||||
if (!this.actions || !this.resourceKey || !this.projectId || !this.saved || !name?.trim()) {
|
||||
return;
|
||||
}
|
||||
|
||||
name = this.projectInfoResource.getNameWithExtension(this.projectId, SCRIPTS_TYPE_ID, name);
|
||||
|
||||
this.lastAction = this.rename.bind(this, name);
|
||||
this.message = 'plugin_sql_editor_navigation_tab_script_state_renaming';
|
||||
|
||||
try {
|
||||
this.exception = null;
|
||||
this.setResourceKey(await this.actions.rename(this, this.resourceKey, createPath(getPathParent(this.resourceKey), name)));
|
||||
} catch (exception: any) {
|
||||
this.exception = exception;
|
||||
} finally {
|
||||
this.message = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async read() {
|
||||
await this.scheduler.schedule(undefined, async () => {
|
||||
if (!this.actions || !this.resourceKey || !this.isOutdated() || !this.saved) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastAction = this.read.bind(this);
|
||||
this.message = 'plugin_sql_editor_navigation_tab_script_state_reading';
|
||||
|
||||
try {
|
||||
this.exception = null;
|
||||
this._script = await this.actions.read(this, this.resourceKey);
|
||||
|
||||
const executionContext = await this.actions.getProperties(this, this.resourceKey);
|
||||
|
||||
runInAction(() => {
|
||||
if (executionContext) {
|
||||
this.setExecutionContext(executionContext);
|
||||
} else {
|
||||
this.setExecutionContext();
|
||||
}
|
||||
});
|
||||
|
||||
this.markUpdated();
|
||||
this.loaded = true;
|
||||
super.setScript(this.script);
|
||||
this.saved = true;
|
||||
} catch (exception: any) {
|
||||
this.exception = exception;
|
||||
} finally {
|
||||
this.message = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async write() {
|
||||
await this.scheduler.schedule(undefined, async () => {
|
||||
if (!this.actions || !this.resourceKey || this.saved) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastAction = this.write.bind(this);
|
||||
this.message = 'plugin_sql_editor_navigation_tab_script_state_saving';
|
||||
|
||||
try {
|
||||
this.exception = null;
|
||||
await this.actions.write(this, this.resourceKey, this.script);
|
||||
this.saved = true;
|
||||
this.markUpdated();
|
||||
} catch (exception: any) {
|
||||
this.exception = exception;
|
||||
} finally {
|
||||
this.message = undefined;
|
||||
}
|
||||
});
|
||||
async load(): Promise<void> {
|
||||
if (this.state.resourceKey && !this.resourceUseKeyId) {
|
||||
this.resourceUseKeyId = this.resourceManagerResource.use(this.state.resourceKey);
|
||||
}
|
||||
await this.read();
|
||||
}
|
||||
|
||||
async save(): Promise<void> {
|
||||
await this.write();
|
||||
await this.saveProperties();
|
||||
try {
|
||||
await this.write();
|
||||
await this.saveProperties();
|
||||
super.save();
|
||||
} catch (exception: any) {
|
||||
this.exception = exception;
|
||||
}
|
||||
}
|
||||
|
||||
private async saveProperties() {
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
this.resourceManagerResource.onItemUpdate.removeHandler(this.syncResource);
|
||||
if (this.state.resourceKey && this.resourceUseKeyId) {
|
||||
this.resourceManagerResource.free(this.state.resourceKey, this.resourceUseKeyId);
|
||||
this.resourceUseKeyId = null;
|
||||
}
|
||||
}
|
||||
|
||||
bindState(state: IResourceSqlDataSourceState): void {
|
||||
this.state = state;
|
||||
this.outdated = true;
|
||||
this.history.restore(state.history);
|
||||
}
|
||||
|
||||
private syncResource(key: ResourceKey<string>) {
|
||||
if (isResourceAlias(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resourceKey = this.resourceKey;
|
||||
if (resourceKey && ResourceKeyUtils.some(key, key => resourceKey.startsWith(key))) {
|
||||
this.markOutdated();
|
||||
}
|
||||
}
|
||||
|
||||
private async rename(name: string) {
|
||||
await this.save();
|
||||
|
||||
await this.scheduler.schedule(undefined, async () => {
|
||||
if (!this.actions || !this.resourceKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastAction = this.rename.bind(this, name);
|
||||
|
||||
try {
|
||||
if (!this.isSaved) {
|
||||
throw new Error('Please save changes before renaming');
|
||||
}
|
||||
this.exception = null;
|
||||
|
||||
this.message = 'plugin_sql_editor_navigation_tab_script_state_renaming';
|
||||
this.setResourceKey(await this.actions.rename(this, this.resourceKey, name));
|
||||
} catch (exception: any) {
|
||||
this.exception = exception;
|
||||
throw exception;
|
||||
} finally {
|
||||
this.message = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async read() {
|
||||
await this.scheduler.schedule(undefined, async () => {
|
||||
if (!this.actions || !this.resourceKey || !this.isOutdated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastAction = this.read.bind(this);
|
||||
|
||||
try {
|
||||
this.exception = null;
|
||||
await this.readData();
|
||||
} catch (exception: any) {
|
||||
this.exception = exception;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async saveProperties() {
|
||||
await this.scheduler.schedule(undefined, async () => {
|
||||
if (!this.actions || !this.resourceKey || this.isExecutionContextSaved) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastAction = this.saveProperties.bind(this);
|
||||
this.message = 'plugin_sql_editor_navigation_tab_script_state_updating';
|
||||
|
||||
try {
|
||||
this.exception = null;
|
||||
|
||||
if (!this.isReadonly()) {
|
||||
this.message = 'plugin_sql_editor_navigation_tab_script_state_updating';
|
||||
const executionContext = await this.actions.setProperties(this, this.resourceKey, this.executionContext);
|
||||
|
||||
if (executionContext) {
|
||||
this.setExecutionContext(executionContext);
|
||||
} else {
|
||||
this.setExecutionContext();
|
||||
}
|
||||
this.setExecutionContext(executionContext);
|
||||
this.setBaseExecutionContext(this.executionContext);
|
||||
}
|
||||
} catch (exception: any) {
|
||||
this.exception = exception;
|
||||
} finally {
|
||||
this.message = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async write() {
|
||||
await this.scheduler.schedule(undefined, async () => {
|
||||
if (!this.actions || !this.resourceKey || this.isScriptSaved) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastAction = this.write.bind(this);
|
||||
|
||||
try {
|
||||
this.exception = null;
|
||||
await this.readData();
|
||||
|
||||
if (!this.isIncomingChanges) {
|
||||
this.message = 'plugin_sql_editor_navigation_tab_script_state_saving';
|
||||
await this.actions.write(this, this.resourceKey, this.script);
|
||||
this.setBaseScript(this.script);
|
||||
}
|
||||
} finally {
|
||||
this.message = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async readData() {
|
||||
try {
|
||||
if (!this.actions || !this.resourceKey) {
|
||||
return;
|
||||
}
|
||||
this.message = 'plugin_sql_editor_navigation_tab_script_state_reading';
|
||||
const script = await this.actions.read(this, this.resourceKey);
|
||||
const executionContext = await this.actions.getProperties(this, this.resourceKey);
|
||||
|
||||
runInAction(() => {
|
||||
if (!this.loaded) {
|
||||
if (this.baseScript !== script) {
|
||||
this.setScript(script);
|
||||
}
|
||||
if (!isObjectsEqual(toJS(this.baseExecutionContext), executionContext)) {
|
||||
this.setExecutionContext(executionContext);
|
||||
}
|
||||
|
||||
this.setBaseScript(script);
|
||||
this.setBaseExecutionContext(executionContext);
|
||||
} else {
|
||||
this.setIncomingExecutionContext(executionContext);
|
||||
this.setIncomingScript(script);
|
||||
}
|
||||
|
||||
this.markUpdated();
|
||||
this.loaded = true;
|
||||
});
|
||||
} finally {
|
||||
this.message = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private debouncedWrite() {
|
||||
this.write();
|
||||
}
|
||||
@@ -394,4 +435,12 @@ export class ResourceSqlDataSource extends BaseSqlDataSource {
|
||||
private debouncedSaveProperties() {
|
||||
this.saveProperties();
|
||||
}
|
||||
|
||||
protected setBaseScript(script: string): void {
|
||||
this.state.baseScript = script;
|
||||
}
|
||||
|
||||
protected setBaseExecutionContext(executionContext: IConnectionExecutionContextInfo | undefined): void {
|
||||
this.state.baseExecutionContext = toJS(executionContext);
|
||||
}
|
||||
}
|
||||
|
||||
+44
-24
@@ -16,12 +16,12 @@ import { getRmResourceKey, IResourceManagerMoveData, ResourceManagerResource } f
|
||||
import { NetworkStateService, WindowEventsService } from '@cloudbeaver/core-root';
|
||||
import { CachedMapAllKey, resourceKeyList, ResourceKeySimple, ResourceKeyUtils } from '@cloudbeaver/core-sdk';
|
||||
import { LocalStorageSaveService } from '@cloudbeaver/core-settings';
|
||||
import { throttle } from '@cloudbeaver/core-utils';
|
||||
import { createPath, getPathParent, throttle } 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';
|
||||
import { ResourceManagerScriptsService } from '@cloudbeaver/plugin-resource-manager-scripts';
|
||||
import { getSqlEditorName, SqlDataSourceService, SqlEditorService } from '@cloudbeaver/plugin-sql-editor';
|
||||
import { ResourceManagerScriptsService, SCRIPTS_TYPE_ID } from '@cloudbeaver/plugin-resource-manager-scripts';
|
||||
import { createSqlDataSourceHistoryInitialState, getSqlEditorName, SqlDataSourceService, SqlEditorService } from '@cloudbeaver/plugin-sql-editor';
|
||||
import { SqlEditorTabService } from '@cloudbeaver/plugin-sql-editor-navigation-tab';
|
||||
|
||||
import type { IResourceSqlDataSourceState } from './IResourceSqlDataSourceState';
|
||||
@@ -70,17 +70,18 @@ export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
for (const [key, value] of Array.from(map.entries())) {
|
||||
if (
|
||||
!['string', 'undefined'].includes(typeof value.resourceKey) ||
|
||||
!['undefined', 'object'].includes(typeof value.executionContext) ||
|
||||
!['string', 'undefined'].includes(typeof value.executionContext?.connectionId) ||
|
||||
!['string', 'undefined'].includes(typeof value.executionContext?.id) ||
|
||||
!['string', 'undefined', 'object'].includes(typeof value.executionContext?.defaultCatalog) ||
|
||||
!['string', 'undefined', 'object'].includes(typeof value.executionContext?.defaultSchema)
|
||||
!['string'].includes(typeof value.script) ||
|
||||
!['string', 'undefined'].includes(typeof value.baseScript) ||
|
||||
isExecutionContextInfoValid(value.executionContext) ||
|
||||
isExecutionContextInfoValid(value.baseExecutionContext)
|
||||
) {
|
||||
map.delete(key);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
},
|
||||
this.bindState.bind(this),
|
||||
'indexed',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -97,20 +98,16 @@ export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
this.connectionInfoResource,
|
||||
this.resourceManagerResource,
|
||||
this.sqlEditorService,
|
||||
this.createState(editorId),
|
||||
this.createState(editorId, options?.script),
|
||||
);
|
||||
|
||||
if (options?.executionContext) {
|
||||
dataSource.setExecutionContext(options.executionContext);
|
||||
}
|
||||
|
||||
if (options?.script) {
|
||||
dataSource.setScript(options.script);
|
||||
}
|
||||
|
||||
if (options?.name) {
|
||||
dataSource.setName(options.name);
|
||||
}
|
||||
// if (options?.name) {
|
||||
// dataSource.setName(options.name);
|
||||
// }
|
||||
|
||||
dataSource.setActions({
|
||||
rename: this.rename.bind(this),
|
||||
@@ -138,15 +135,11 @@ export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
},
|
||||
onDestroy: (_, editorId) => this.deleteState(editorId),
|
||||
onUnload: async dataSource => {
|
||||
if (dataSource instanceof ResourceSqlDataSource) {
|
||||
await dataSource.write();
|
||||
}
|
||||
await dataSource.save();
|
||||
},
|
||||
canDestroy: async (dataSource, editorId) => {
|
||||
try {
|
||||
if (dataSource instanceof ResourceSqlDataSource) {
|
||||
await dataSource.write();
|
||||
}
|
||||
await dataSource.save();
|
||||
} catch {
|
||||
const tab = this.sqlEditorTabService.sqlEditorTabs.find(tab => tab.handlerState.editorId === editorId);
|
||||
let name: string | undefined = undefined;
|
||||
@@ -173,12 +166,15 @@ export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
|
||||
load(): void | Promise<void> {}
|
||||
|
||||
private createState(editorId: string, resourceKey?: string): IResourceSqlDataSourceState {
|
||||
private createState(editorId: string, script?: string, resourceKey?: string): IResourceSqlDataSourceState {
|
||||
let state = this.dataSourceStateState.get(editorId);
|
||||
|
||||
if (!state) {
|
||||
state = observable<IResourceSqlDataSourceState>({
|
||||
script: script ?? '',
|
||||
baseScript: script ?? '',
|
||||
resourceKey,
|
||||
history: createSqlDataSourceHistoryInitialState(script),
|
||||
});
|
||||
|
||||
this.dataSourceStateState.set(editorId, state);
|
||||
@@ -250,12 +246,18 @@ export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
this.navigationTabsService.closeTabSilent(resourceKeyList(tabs), true);
|
||||
}
|
||||
|
||||
private async rename(dataSource: ResourceSqlDataSource, resourceKey: string, newResourceKey: string): Promise<string> {
|
||||
private async rename(dataSource: ResourceSqlDataSource, resourceKey: string, name: string): Promise<string> {
|
||||
if (!dataSource.projectId) {
|
||||
throw new Error('Project ID is not defined');
|
||||
}
|
||||
if (!this.resourceManagerService.enabled) {
|
||||
throw new Error('Resource Manager disabled');
|
||||
}
|
||||
|
||||
try {
|
||||
name = this.projectInfoResource.getNameWithExtension(dataSource.projectId, SCRIPTS_TYPE_ID, name);
|
||||
const newResourceKey = createPath(getPathParent(resourceKey), name);
|
||||
|
||||
await this.navResourceNodeService.move(resourceKey, newResourceKey);
|
||||
return newResourceKey;
|
||||
} catch (exception) {
|
||||
@@ -308,4 +310,22 @@ export class ResourceSqlDataSourceBootstrap extends Bootstrap {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
private bindState() {
|
||||
for (const [editorId, datasource] of this.sqlDataSourceService.dataSources) {
|
||||
if (datasource instanceof ResourceSqlDataSource) {
|
||||
datasource.bindState(this.createState(editorId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isExecutionContextInfoValid(executionContext: IConnectionExecutionContextInfo | undefined) {
|
||||
return (
|
||||
!['undefined', 'object'].includes(typeof executionContext) ||
|
||||
!['string', 'undefined'].includes(typeof executionContext?.connectionId) ||
|
||||
!['string', 'undefined'].includes(typeof executionContext?.id) ||
|
||||
!['string', 'undefined', 'object'].includes(typeof executionContext?.defaultCatalog) ||
|
||||
!['string', 'undefined', 'object'].includes(typeof executionContext?.defaultSchema)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user