mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-16 14:50:15 +08:00
Compare commits
5
Commits
release_26_1_2
...
24.1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad218fd0cc | ||
|
|
034e7d6146 | ||
|
|
6a2a4ed042 | ||
|
|
fdfa20d6c8 | ||
|
|
b12b2d813e |
+21
-19
@@ -256,18 +256,20 @@ public class LocalResourceController implements RMController {
|
||||
return new RMProject[0];
|
||||
}
|
||||
var projects = new ArrayList<RMProject>();
|
||||
var allPaths = Files.list(sharedProjectsPath).collect(Collectors.toList());
|
||||
for (Path path : allPaths) {
|
||||
var projectPerms = getProjectPermissions(
|
||||
makeProjectIdFromPath(path, RMProjectType.SHARED),
|
||||
RMProjectType.SHARED
|
||||
);
|
||||
var rmProject = makeProjectFromPath(path, projectPerms, RMProjectType.SHARED, false);
|
||||
projects.add(rmProject);
|
||||
try (Stream<Path> list = Files.list(sharedProjectsPath)) {
|
||||
var allPaths = list.toList();
|
||||
for (Path path : allPaths) {
|
||||
var projectPerms = getProjectPermissions(
|
||||
makeProjectIdFromPath(path, RMProjectType.SHARED),
|
||||
RMProjectType.SHARED
|
||||
);
|
||||
var rmProject = makeProjectFromPath(path, projectPerms, RMProjectType.SHARED, false);
|
||||
projects.add(rmProject);
|
||||
}
|
||||
return projects.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.toArray(RMProject[]::new);
|
||||
}
|
||||
return projects.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.toArray(RMProject[]::new);
|
||||
} catch (IOException e) {
|
||||
throw new DBException("Error reading shared projects", e);
|
||||
}
|
||||
@@ -581,7 +583,7 @@ public class LocalResourceController implements RMController {
|
||||
@NotNull String resourcePath,
|
||||
boolean isFolder
|
||||
) throws DBException {
|
||||
try (var projectLock = lockController.lockProject(projectId, "createResource")) {
|
||||
try (var ignoredLock = lockController.lockProject(projectId, "createResource")) {
|
||||
validateResourcePath(resourcePath);
|
||||
Path targetPath = getTargetPath(projectId, resourcePath);
|
||||
if (Files.exists(targetPath)) {
|
||||
@@ -613,7 +615,7 @@ public class LocalResourceController implements RMController {
|
||||
@NotNull String oldResourcePath,
|
||||
@NotNull String newResourcePath
|
||||
) throws DBException {
|
||||
try (var projectLock = lockController.lockProject(projectId, "moveResource")) {
|
||||
try (var ignoredLock = lockController.lockProject(projectId, "moveResource")) {
|
||||
var normalizedOldResourcePath = CommonUtils.normalizeResourcePath(oldResourcePath);
|
||||
var normalizedNewResourcePath = CommonUtils.normalizeResourcePath(newResourcePath);
|
||||
if (log.isDebugEnabled()) {
|
||||
@@ -679,7 +681,7 @@ public class LocalResourceController implements RMController {
|
||||
|
||||
@Override
|
||||
public void deleteResource(@NotNull String projectId, @NotNull String resourcePath, boolean recursive) throws DBException {
|
||||
try (var projectLock = lockController.lockProject(projectId, "deleteResource")) {
|
||||
try (var ignoredLock = lockController.lockProject(projectId, "deleteResource")) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Removing resource from '" + resourcePath + "' in project '" + projectId + "'" + (recursive ? " recursive" : ""));
|
||||
}
|
||||
@@ -768,7 +770,7 @@ public class LocalResourceController implements RMController {
|
||||
@NotNull byte[] data,
|
||||
boolean forceOverwrite
|
||||
) throws DBException {
|
||||
try (var lock = lockController.lockProject(projectId, "setResourceContents")) {
|
||||
try (var ignoredLock = lockController.lockProject(projectId, "setResourceContents")) {
|
||||
validateResourcePath(resourcePath);
|
||||
Number fileSizeLimit = WebAppUtils.getWebApplication()
|
||||
.getAppConfiguration()
|
||||
@@ -822,7 +824,7 @@ public class LocalResourceController implements RMController {
|
||||
@NotNull String propertyName,
|
||||
@Nullable Object propertyValue
|
||||
) throws DBException {
|
||||
try (var projectLock = lockController.lockProject(projectId, "resourcePropertyUpdate")) {
|
||||
try (var ignoredLock = lockController.lockProject(projectId, "resourcePropertyUpdate")) {
|
||||
validateResourcePath(resourcePath);
|
||||
BaseWebProjectImpl webProject = getWebProject(projectId, false);
|
||||
doFileWriteOperation(projectId, webProject.getMetadataFilePath(),
|
||||
@@ -843,7 +845,7 @@ public class LocalResourceController implements RMController {
|
||||
@NotNull String resourcePath,
|
||||
@NotNull Map<String, Object> properties
|
||||
) throws DBException {
|
||||
try (var projectLock = lockController.lockProject(projectId, "resourcePropertyUpdate")) {
|
||||
try (var ignoredLock = lockController.lockProject(projectId, "resourcePropertyUpdate")) {
|
||||
validateResourcePath(resourcePath);
|
||||
BaseWebProjectImpl webProject = getWebProject(projectId, false);
|
||||
doFileWriteOperation(projectId, webProject.getMetadataFilePath(),
|
||||
@@ -1110,7 +1112,7 @@ public class LocalResourceController implements RMController {
|
||||
);
|
||||
}
|
||||
if (readProperties) {
|
||||
final BaseProjectImpl project = (BaseProjectImpl) getWebProject(projectId, true);
|
||||
final BaseProjectImpl project = getWebProject(projectId, true);
|
||||
final String resourcePath = getProjectRelativePath(projectId, path);
|
||||
final Map<String, Object> properties = project.getResourceProperties(resourcePath);
|
||||
|
||||
@@ -1155,7 +1157,7 @@ public class LocalResourceController implements RMController {
|
||||
);
|
||||
}
|
||||
|
||||
private void fireRmProjectAddEvent(@NotNull RMProject project) throws DBException {
|
||||
private void fireRmProjectAddEvent(@NotNull RMProject project) {
|
||||
RMEventManager.fireEvent(
|
||||
new RMEvent(
|
||||
RMEvent.Action.RESOURCE_ADD,
|
||||
|
||||
@@ -43,6 +43,7 @@ import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class RMNIOTest {
|
||||
|
||||
@@ -135,12 +136,14 @@ public class RMNIOTest {
|
||||
String file2 = "script" + SecurityUtils.generateUniqueId() + ".sql";
|
||||
rm.createResource(testProject.getId(), file1, true);
|
||||
rm.createResource(testProject.getId(), file2, false);
|
||||
Set<String> filesFromNio =
|
||||
Files.list(rootPath)
|
||||
.map(path -> ((RMPath) path).getResourcePath())
|
||||
.collect(Collectors.toSet());
|
||||
Assert.assertTrue(filesFromNio.contains(file1));
|
||||
Assert.assertTrue(filesFromNio.contains(file2));
|
||||
try (Stream<Path> list = Files.list(rootPath)) {
|
||||
Set<String> filesFromNio =
|
||||
list
|
||||
.map(path -> ((RMPath) path).getResourcePath())
|
||||
.collect(Collectors.toSet());
|
||||
Assert.assertTrue(filesFromNio.contains(file1));
|
||||
Assert.assertTrue(filesFromNio.contains(file2));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -31,7 +31,7 @@ export class DataViewerDataChangeConfirmationService {
|
||||
const model = this.dataViewerTableService.get(modelId);
|
||||
|
||||
if (model && !model.onRequest.hasHandler(this.checkUnsavedData)) {
|
||||
model.onRequest.addHandler(executorHandlerFilter(({ operation }) => operation !== DatabaseDataSourceOperation.Save, this.checkUnsavedData));
|
||||
model.onRequest.addHandler(executorHandlerFilter(({ operation }) => operation === DatabaseDataSourceOperation.Request, this.checkUnsavedData));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,14 +111,7 @@ export class DataViewerTabService {
|
||||
const model = this.tableViewerStorageService.get(tab.handlerState.tableId || '');
|
||||
|
||||
if (model) {
|
||||
let canClose = false;
|
||||
try {
|
||||
await model.source.runTask(async () => {
|
||||
canClose = true;
|
||||
});
|
||||
} catch {}
|
||||
|
||||
return canClose;
|
||||
return await model.source.canSafelyDispose();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+11
-3
@@ -125,7 +125,7 @@ export class ResultSetDataContentAction extends DatabaseDataAction<any, IDatabas
|
||||
throw new Error('Failed to get value metadata information');
|
||||
}
|
||||
|
||||
const fullText = await this.source.runTask(async () => {
|
||||
const fullText = await this.source.runOperation(async () => {
|
||||
try {
|
||||
this.updateCache(element, { loading: true });
|
||||
return await this.loadFileFullText(this.result, column.position, row);
|
||||
@@ -134,6 +134,10 @@ export class ResultSetDataContentAction extends DatabaseDataAction<any, IDatabas
|
||||
}
|
||||
});
|
||||
|
||||
if (fullText === null) {
|
||||
throw new Error('Failed to get value metadata information');
|
||||
}
|
||||
|
||||
this.updateCache(element, { fullText });
|
||||
|
||||
return fullText;
|
||||
@@ -167,7 +171,7 @@ export class ResultSetDataContentAction extends DatabaseDataAction<any, IDatabas
|
||||
this.clearCache();
|
||||
}
|
||||
|
||||
private async getFileDataUrl(element: IResultSetElementKey) {
|
||||
private async getFileDataUrl(element: IResultSetElementKey): Promise<string> {
|
||||
const column = this.data.getColumn(element.column);
|
||||
const row = this.data.getRowValue(element.row);
|
||||
|
||||
@@ -175,7 +179,7 @@ export class ResultSetDataContentAction extends DatabaseDataAction<any, IDatabas
|
||||
throw new Error('Failed to get value metadata information');
|
||||
}
|
||||
|
||||
const url = await this.source.runTask(async () => {
|
||||
const url = await this.source.runOperation(async () => {
|
||||
try {
|
||||
this.updateCache(element, { loading: true });
|
||||
return await this.loadDataURL(this.result, column.position, row);
|
||||
@@ -184,6 +188,10 @@ export class ResultSetDataContentAction extends DatabaseDataAction<any, IDatabas
|
||||
}
|
||||
});
|
||||
|
||||
if (url === null) {
|
||||
throw new Error('Failed to get value metadata information');
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ export abstract class DatabaseDataSource<TOptions, TResult extends IDatabaseData
|
||||
private get activeOperation(): Promise<void> | null {
|
||||
return this.activeOperationStack[this.activeOperationStack.length - 1] ?? null;
|
||||
}
|
||||
private readonly activeOperationStack: Array<Promise<void>>;
|
||||
private readonly activeOperationStack: Array<Promise<any>>;
|
||||
|
||||
constructor(serviceInjector: IServiceInjector) {
|
||||
this.serviceInjector = serviceInjector;
|
||||
@@ -286,12 +286,12 @@ export abstract class DatabaseDataSource<TOptions, TResult extends IDatabaseData
|
||||
await this.lastAction();
|
||||
}
|
||||
|
||||
async runTask(task: () => Promise<any>): Promise<any> {
|
||||
async runOperation<T>(task: () => Promise<T>): Promise<T | null> {
|
||||
return this.tryExecuteOperation(DatabaseDataSourceOperation.Task, task);
|
||||
}
|
||||
|
||||
async requestData(mutation?: () => void): Promise<void> {
|
||||
await this.tryExecuteOperation(DatabaseDataSourceOperation.Load, () => {
|
||||
await this.tryExecuteOperation(DatabaseDataSourceOperation.Request, () => {
|
||||
this.lastAction = this.requestData.bind(this);
|
||||
|
||||
mutation?.();
|
||||
@@ -300,7 +300,7 @@ export abstract class DatabaseDataSource<TOptions, TResult extends IDatabaseData
|
||||
}
|
||||
|
||||
async requestDataPortion(offset: number, count: number): Promise<void> {
|
||||
await this.tryExecuteOperation(DatabaseDataSourceOperation.Load, () => {
|
||||
await this.tryExecuteOperation<TResult[] | void>(DatabaseDataSourceOperation.Request, () => {
|
||||
if (!this.isDataAvailable(offset, count)) {
|
||||
this.lastAction = this.requestDataPortion.bind(this, offset, count);
|
||||
|
||||
@@ -312,7 +312,7 @@ export abstract class DatabaseDataSource<TOptions, TResult extends IDatabaseData
|
||||
}
|
||||
|
||||
async refreshData(): Promise<void> {
|
||||
await this.tryExecuteOperation(DatabaseDataSourceOperation.Refresh, () => {
|
||||
await this.tryExecuteOperation(DatabaseDataSourceOperation.Request, () => {
|
||||
this.lastAction = this.refreshData.bind(this);
|
||||
|
||||
if (this.prevOptions) {
|
||||
@@ -333,6 +333,15 @@ export abstract class DatabaseDataSource<TOptions, TResult extends IDatabaseData
|
||||
});
|
||||
}
|
||||
|
||||
async canSafelyDispose(): Promise<boolean> {
|
||||
try {
|
||||
const result = await this.tryExecuteOperation(DatabaseDataSourceOperation.Request, async () => true);
|
||||
return result || false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
clearError(): this {
|
||||
this.error = null;
|
||||
return this;
|
||||
@@ -358,7 +367,7 @@ export abstract class DatabaseDataSource<TOptions, TResult extends IDatabaseData
|
||||
abstract loadTotalCount(resultIndex: number): Promise<ITask<number>>;
|
||||
abstract cancelLoadTotalCount(): Promise<ITask<number> | null>;
|
||||
|
||||
private async requestDataAction(): Promise<TResult[] | null> {
|
||||
private async requestDataAction(): Promise<TResult[]> {
|
||||
this.prevOptions = toJS(this.options);
|
||||
return this.request(this.results).then(data => {
|
||||
this.outdated = false;
|
||||
@@ -370,8 +379,8 @@ export abstract class DatabaseDataSource<TOptions, TResult extends IDatabaseData
|
||||
});
|
||||
}
|
||||
|
||||
private async tryExecuteOperation(type: DatabaseDataSourceOperation, operation: () => Promise<any>): Promise<void> {
|
||||
if (this.activeOperation && type !== DatabaseDataSourceOperation.Task && type !== DatabaseDataSourceOperation.Save) {
|
||||
private async tryExecuteOperation<T>(type: DatabaseDataSourceOperation, operation: () => Promise<T>): Promise<T | null> {
|
||||
if (this.activeOperation && type !== DatabaseDataSourceOperation.Request) {
|
||||
await this.activeOperation;
|
||||
}
|
||||
|
||||
@@ -387,23 +396,25 @@ export abstract class DatabaseDataSource<TOptions, TResult extends IDatabaseData
|
||||
}
|
||||
}
|
||||
|
||||
private executeOperation(type: DatabaseDataSourceOperation, operation: () => Promise<void> | void): ITask<void> {
|
||||
private executeOperation<T>(type: DatabaseDataSourceOperation, operation: () => Promise<T> | T): ITask<T | null> {
|
||||
return new Task(async () => await this.onOperation.execute({ stage: 'request', operation: type })).run().then(contexts => {
|
||||
// TODO: maybe it's better to throw an exception instead, so we will not have unexpected undefined results
|
||||
if (ExecutorInterrupter.isInterrupted(contexts)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Task(async () => await this.onOperation.execute({ stage: 'before', operation: type }))
|
||||
.run()
|
||||
.then(contexts => {
|
||||
if (ExecutorInterrupter.isInterrupted(contexts)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
return operation();
|
||||
})
|
||||
.then(async () => {
|
||||
.then(async result => {
|
||||
await this.onOperation.execute({ stage: 'after', operation: type });
|
||||
return result;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -15,10 +15,12 @@ import type { IDatabaseDataActions } from './IDatabaseDataActions';
|
||||
import type { IDatabaseDataResult } from './IDatabaseDataResult';
|
||||
|
||||
export enum DatabaseDataSourceOperation {
|
||||
Load = 'load',
|
||||
Save = 'save',
|
||||
Refresh = 'refresh',
|
||||
/** Abstract operation with data, should not lead to data lost */
|
||||
Task = 'task',
|
||||
/** Saving operation */
|
||||
Save = 'save',
|
||||
/** May lead to data lost */
|
||||
Request = 'request',
|
||||
}
|
||||
export interface IDatabaseDataSourceOperationEvent {
|
||||
stage: 'request' | 'before' | 'after';
|
||||
@@ -102,15 +104,19 @@ export interface IDatabaseDataSource<TOptions, TResult extends IDatabaseDataResu
|
||||
cancelLoadTotalCount: () => Promise<ITask<number> | null>;
|
||||
|
||||
retry: () => Promise<void>;
|
||||
/** Allows to perform an asynchronous action on the data source, this action will wait previous action to finish and save or load requests.
|
||||
* The data source will have a loading and disabled state while performing an action */
|
||||
runTask: <T>(task: () => Promise<T>) => Promise<T>;
|
||||
/**
|
||||
* Perform operation with data source. This action should not lead to data lost. Can be cancelled when operation is Task.
|
||||
* @param operation Task or Promise
|
||||
* @returns
|
||||
*/
|
||||
runOperation: <T>(operation: () => Promise<T>) => Promise<T | null>;
|
||||
requestDataPortion(offset: number, count: number): Promise<void>;
|
||||
requestData: (mutation?: () => void) => Promise<void> | void;
|
||||
refreshData: () => Promise<void> | void;
|
||||
saveData: () => Promise<void> | void;
|
||||
cancel: () => Promise<void> | void;
|
||||
requestData: (mutation?: () => void) => Promise<void>;
|
||||
refreshData: () => Promise<void>;
|
||||
saveData: () => Promise<void>;
|
||||
cancel: () => Promise<void>;
|
||||
clearError: () => this;
|
||||
resetData: () => this;
|
||||
canSafelyDispose: () => Promise<boolean>;
|
||||
dispose: (keepExecutionContext?: boolean) => Promise<void>;
|
||||
}
|
||||
|
||||
+7
-1
@@ -7,4 +7,10 @@
|
||||
*/
|
||||
import { ACTION_REFRESH, createMenu } from '@cloudbeaver/core-view';
|
||||
|
||||
export const MENU_DATA_VIEWER_AUTO_REFRESH = createMenu('auto-refresh', 'Auto-Refresh', undefined, 'data_viewer_action_auto_refresh', ACTION_REFRESH);
|
||||
export const MENU_DATA_VIEWER_AUTO_REFRESH = createMenu(
|
||||
'auto-refresh',
|
||||
'data_viewer_action_auto_refresh',
|
||||
undefined,
|
||||
'data_viewer_action_auto_refresh',
|
||||
ACTION_REFRESH,
|
||||
);
|
||||
|
||||
+23
-4
@@ -13,7 +13,7 @@ import { Bootstrap, injectable } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dialogs';
|
||||
import { LocalizationService } from '@cloudbeaver/core-localization';
|
||||
import { declensionOfNumber } from '@cloudbeaver/core-utils';
|
||||
import { ACTION_REFRESH, ActionService, MenuBaseItem, menuExtractItems, MenuService } from '@cloudbeaver/core-view';
|
||||
import { ACTION_REFRESH, ActionService, MenuBaseItem, menuExtractItems, MenuSeparatorItem, MenuService } from '@cloudbeaver/core-view';
|
||||
|
||||
import { IDatabaseRefreshState } from '../../../../DatabaseDataModel/Actions/DatabaseRefreshAction';
|
||||
import { DATA_CONTEXT_DV_DDM } from '../../../../DatabaseDataModel/DataContext/DATA_CONTEXT_DV_DDM';
|
||||
@@ -72,12 +72,13 @@ export class TableRefreshActionBootstrap extends Bootstrap {
|
||||
const state = getRefreshState(context);
|
||||
items = [...items];
|
||||
for (const interval of AUTO_REFRESH_INTERVALS) {
|
||||
const label = this.getLabel(interval);
|
||||
items.push(
|
||||
new MenuBaseItem(
|
||||
{
|
||||
id: `auto-refresh-${interval}`,
|
||||
label: this.getLabel(interval),
|
||||
tooltip: 'data_viewer_action_auto_refresh',
|
||||
label,
|
||||
tooltip: label,
|
||||
disabled: state?.interval === interval * 1000,
|
||||
},
|
||||
{
|
||||
@@ -89,12 +90,14 @@ export class TableRefreshActionBootstrap extends Bootstrap {
|
||||
);
|
||||
}
|
||||
|
||||
items.push(new MenuSeparatorItem());
|
||||
|
||||
items.push(
|
||||
new MenuBaseItem(
|
||||
{
|
||||
id: 'auto-refresh-custom',
|
||||
label: 'ui_custom',
|
||||
tooltip: 'data_viewer_action_auto_refresh',
|
||||
tooltip: 'plugin_data_viewer_action_auto_refresh_custom',
|
||||
},
|
||||
{
|
||||
onSelect: this.configureAutoRefresh.bind(this, context),
|
||||
@@ -102,6 +105,22 @@ export class TableRefreshActionBootstrap extends Bootstrap {
|
||||
),
|
||||
);
|
||||
|
||||
items.push(
|
||||
new MenuBaseItem(
|
||||
{
|
||||
id: 'auto-refresh-stop',
|
||||
label: 'ui_processing_stop',
|
||||
tooltip: 'data_viewer_action_auto_refresh_stop',
|
||||
disabled: !state?.isAutoRefresh,
|
||||
},
|
||||
{
|
||||
onSelect: () => {
|
||||
state?.setInterval(0);
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
return items;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -21,6 +21,7 @@ export default [
|
||||
['data_viewer_action_refresh', 'Refresh'],
|
||||
['data_viewer_action_auto_refresh', 'Auto-Refresh'],
|
||||
['data_viewer_action_auto_refresh_stop', 'Stop auto-refresh'],
|
||||
['plugin_data_viewer_action_auto_refresh_custom', 'Configure auto-refresh'],
|
||||
['data_viewer_action_edit_delete', 'Delete selected'],
|
||||
['data_viewer_action_edit_add', 'Add'],
|
||||
['data_viewer_action_edit_add_copy', 'Duplicate'],
|
||||
@@ -28,7 +29,7 @@ export default [
|
||||
['data_viewer_result_edited_title', 'Save changes'],
|
||||
['data_viewer_result_edited_message', 'Result set was edited. Do you want to save changes in database?'],
|
||||
['data_viewer_data_save_error_title', 'Error occurred while saving changes'],
|
||||
['data_viewer_auto_refresh_settings', 'Auto refresh Settings'],
|
||||
['data_viewer_auto_refresh_settings', 'Auto-Refresh Settings'],
|
||||
['data_viewer_auto_refresh_settings_stop_on_error', 'Stop on error'],
|
||||
['data_viewer_presentation_value_no_active_elements', 'No selected table cells'],
|
||||
['data_viewer_presentation_value_title', 'Value'],
|
||||
|
||||
@@ -21,6 +21,7 @@ export default [
|
||||
['data_viewer_action_refresh', 'Actualiser'],
|
||||
['data_viewer_action_auto_refresh', 'Actualisation automatique'],
|
||||
['data_viewer_action_auto_refresh_stop', "Arrêter l'actualisation automatique"],
|
||||
['plugin_data_viewer_action_auto_refresh_custom', 'Configure auto-refresh'],
|
||||
['data_viewer_action_edit_delete', 'Supprimer la sélection'],
|
||||
['data_viewer_action_edit_add', 'Ajouter'],
|
||||
['data_viewer_action_edit_add_copy', 'Dupliquer'],
|
||||
|
||||
@@ -21,10 +21,11 @@ export default [
|
||||
['data_viewer_action_refresh', 'Refresh'],
|
||||
['data_viewer_action_auto_refresh', 'Auto-Refresh'],
|
||||
['data_viewer_action_auto_refresh_stop', 'Stop auto-refresh'],
|
||||
['plugin_data_viewer_action_auto_refresh_custom', 'Configure auto-refresh'],
|
||||
['data_viewer_result_edited_title', 'Save changes'],
|
||||
['data_viewer_result_edited_message', 'Result set was edited. Do you want to save changes in database?'],
|
||||
['data_viewer_data_save_error_title', 'Error occurred while saving changes'],
|
||||
['data_viewer_auto_refresh_settings', 'Auto refresh Settings'],
|
||||
['data_viewer_auto_refresh_settings', 'Auto-Refresh Settings'],
|
||||
['data_viewer_auto_refresh_settings_stop_on_error', 'Stop on error'],
|
||||
['data_viewer_presentation_value_no_active_elements', 'No selected table cells'],
|
||||
['data_viewer_presentation_value_title', 'Valore'],
|
||||
|
||||
@@ -21,6 +21,7 @@ export default [
|
||||
['data_viewer_action_refresh', 'Обновить'],
|
||||
['data_viewer_action_auto_refresh', 'Автообновление'],
|
||||
['data_viewer_action_auto_refresh_stop', 'Остановить автообновление'],
|
||||
['plugin_data_viewer_action_auto_refresh_custom', 'Настроить автообновление'],
|
||||
['data_viewer_action_edit_delete', 'Удалить'],
|
||||
['data_viewer_action_edit_add', 'Добавить'],
|
||||
['data_viewer_action_edit_add_copy', 'Дублировать'],
|
||||
|
||||
@@ -21,6 +21,7 @@ export default [
|
||||
['data_viewer_action_refresh', 'Refresh'],
|
||||
['data_viewer_action_auto_refresh', 'Auto-Refresh'],
|
||||
['data_viewer_action_auto_refresh_stop', 'Stop auto-refresh'],
|
||||
['plugin_data_viewer_action_auto_refresh_custom', 'Configure auto-refresh'],
|
||||
['data_viewer_action_edit_delete', '删除选中'],
|
||||
['data_viewer_action_edit_add', '添加'],
|
||||
['data_viewer_action_edit_add_copy', 'Duplicate'],
|
||||
@@ -28,7 +29,7 @@ export default [
|
||||
['data_viewer_result_edited_title', '保存更改'],
|
||||
['data_viewer_result_edited_message', '结果集已编辑。是否将更改保存到数据库?'],
|
||||
['data_viewer_data_save_error_title', 'Error occurred while saving changes'],
|
||||
['data_viewer_auto_refresh_settings', 'Auto refresh Settings'],
|
||||
['data_viewer_auto_refresh_settings', 'Auto-Refresh Settings'],
|
||||
['data_viewer_auto_refresh_settings_stop_on_error', 'Stop on error'],
|
||||
['data_viewer_presentation_value_no_active_elements', 'No selected table cells'],
|
||||
['data_viewer_presentation_value_title', '值'],
|
||||
|
||||
@@ -136,14 +136,7 @@ export class SqlQueryResultService {
|
||||
const model = this.tableViewerStorageService.get(group.modelId);
|
||||
|
||||
if (model) {
|
||||
let canClose = false;
|
||||
|
||||
try {
|
||||
await model.source.runTask(async () => {
|
||||
canClose = true;
|
||||
});
|
||||
} catch {}
|
||||
return canClose;
|
||||
return await model.source.canSafelyDispose();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -24,7 +24,11 @@ export class ScriptPreviewService {
|
||||
|
||||
async open(model: IDatabaseDataModel, resultIndex: number): Promise<void> {
|
||||
try {
|
||||
const script = await model.source.runTask(() => this.tryGetScript(model, resultIndex));
|
||||
const script = await model.source.runOperation(() => this.tryGetScript(model, resultIndex));
|
||||
|
||||
if (script === null) {
|
||||
throw new Error('Script is not provided');
|
||||
}
|
||||
|
||||
this.commonDialogService.open(ScriptPreviewDialog, {
|
||||
script,
|
||||
|
||||
Reference in New Issue
Block a user