Merge remote-tracking branch 'origin/devel' into chore/cb-2548/product-information-design

This commit is contained in:
Wroud
2022-09-09 12:13:45 +03:00
25 changed files with 136 additions and 151 deletions
+28
View File
@@ -22,6 +22,34 @@ You can see live demo of CloudBeaver here: https://demo.cloudbeaver.io
## Changelog
### CloudBeaver 22.2.0 - 2022-09-06
Changes since 22.1.0
- Public page:
- administrators can create shared connections via the Connection menu.
- Resource Manager:
- users can group scripts into folders;
- when internet connection is lost, script editing is disabled to prevent users from losing data;
- users can refresh all scripts by clicking one button;
- users can rename scripts.
- Database Navigator:
- users can group connections into folders.
- SQL Editor:
- "Link with Editor" tool is now available for the SQL Editor and synchronizes it with the element in the Database Navigator;
- script formatting can be undone.
- The Data Editor:
- non-editable tables are marked;
- users can change the coordinate system for spatial data in the Value panel.
- Local configuration:
- the application language can be set;
- the number of table rows to load can be configured to prevent the application from slowing down in the following cases:
- the default number of loaded rows when users open a table and then scroll it,
- the minimum and maximum number of rows, which users can load at once when scrolling the table;
- SQL query execution time limit can be changed;
- The cookies can be disabled.
- The product upgrade scripts were improved to avoid possible UI issues.
- A lot of small bug fixes, enhancements and improvements have been made.
### CloudBeaver 22.1.4 - 2022-08-08
- Local configuration:
- The structure of the local configuration file has been improved to simplify the modification process;
@@ -22,9 +22,10 @@ package io.cloudbeaver;
public class DBWConstants {
public static final String PERMISSION_PUBLIC = "public";
public static final String PERMISSION_ADMIN = "admin";
public static final String PERMISSION_CONFIGURATION_MANAGER = "configuration-manager";
public static final String PERMISSION_EDIT_STRUCTURE = "edit-meta";
public static final String PERMISSION_EDIT_DATA = "edit-data";
@@ -17,7 +17,7 @@
package io.cloudbeaver.model.app;
import io.cloudbeaver.DataSourceFilter;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.VirtualProjectImpl;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.app.DBPApplication;
@@ -27,7 +27,6 @@ import org.jkiss.dbeaver.model.rm.RMController;
import org.jkiss.dbeaver.model.rm.RMProject;
import org.jkiss.dbeaver.model.security.SMAdminController;
import org.jkiss.dbeaver.model.security.SMController;
import io.cloudbeaver.VirtualProjectImpl;
import java.nio.file.Path;
@@ -41,6 +40,8 @@ public interface WebApplication extends DBPApplication {
Path getDataDirectory(boolean create);
Path getWorkspaceDirectory();
Path getHomeDirectory();
boolean isMultiNode();
@@ -204,7 +204,7 @@ public class LocalResourceController implements RMController {
public RMProject createProject(@NotNull String name, @Nullable String description) throws DBException {
if (!Files.exists(sharedProjectsPath)) {
try {
Files.createDirectory(sharedProjectsPath);
Files.createDirectories(sharedProjectsPath);
} catch (IOException e) {
throw new DBException("Error creating shared project path", e);
}
@@ -216,7 +216,7 @@ public class LocalResourceController implements RMController {
throw new DBException("Project '" + name + "' already exists");
}
try {
Files.createDirectory(getProjectPath(project.getId()));
Files.createDirectories(getProjectPath(project.getId()));
return project;
} catch (IOException e) {
throw new DBException("Error creating project path", e);
@@ -354,7 +354,7 @@ public class LocalResourceController implements RMController {
}
try {
if (isFolder) {
Files.createDirectory(targetPath);
Files.createDirectories(targetPath);
} else {
Files.createFile(targetPath);
}
@@ -1,65 +0,0 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2022 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.cloudbeaver.model.session;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.auth.SMAuthSpace;
import org.jkiss.dbeaver.model.auth.SMAuthToken;
import org.jkiss.dbeaver.model.auth.SMSession;
import org.jkiss.dbeaver.model.auth.SMSessionContext;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
public class SMWebSessionContext implements SMSessionContext {
private final WebSession session;
private final SMSessionContext parentContext;
public SMWebSessionContext(SMSessionContext parentContext, WebSession session) {
this.parentContext = parentContext;
this.session = session;
}
@Nullable
@Override
public SMSession getSpaceSession(@NotNull DBRProgressMonitor monitor, @NotNull SMAuthSpace space, boolean open) throws DBException {
return parentContext.getSpaceSession(monitor, session.getSessionSpace(), open);
}
@Nullable
@Override
public SMSession findSpaceSession(@NotNull SMAuthSpace space) {
return parentContext.findSpaceSession(session.getSessionSpace());
}
@Override
public SMAuthToken[] getSavedTokens() {
return parentContext.getSavedTokens();
}
@Override
public void addSession(@NotNull SMSession session) {
parentContext.addSession(session);
}
@Override
public boolean removeSession(@NotNull SMSession session) {
return parentContext.removeSession(session);
}
}
@@ -352,10 +352,9 @@ public class WebSession extends AbstractSessionPersistent implements SMSession,
public VirtualProjectImpl createVirtualProject(RMProject project) {
// Do not filter data sources from user project
DataSourceFilter filter = project.getType() == RMProject.Type.USER ? x -> true : this::isDataSourceAccessible;
SMSessionContext projectSessionContext = new SMWebSessionContext(sessionAuthContext, this);
VirtualProjectImpl sessionProject = application.createProjectImpl(
project,
projectSessionContext,
sessionAuthContext,
this,
filter);
DBPDataSourceRegistry dataSourceRegistry = sessionProject.getDataSourceRegistry();
@@ -958,8 +957,10 @@ public class WebSession extends AbstractSessionPersistent implements SMSession,
}
public synchronized void updateSMAuthInfo(SMAuthInfo smAuthInfo) throws DBException {
userContext.refresh(smAuthInfo);
refreshUserData();
boolean contextChanged = userContext.refresh(smAuthInfo);
if (contextChanged) {
refreshUserData();
}
}
@Override
@@ -65,7 +65,7 @@ public class WebUserContext implements SMCredentialsProvider {
* @param smAuthInfo - auth info from security manager
* @throws DBException - if user already authorized and new token come from another user
*/
public synchronized void refresh(SMAuthInfo smAuthInfo) throws DBException {
public synchronized boolean refresh(SMAuthInfo smAuthInfo) throws DBException {
if (smAuthInfo.getAuthStatus() != SMAuthStatus.SUCCESS) {
throw new DBCException("Authorization did not complete successfully");
}
@@ -92,7 +92,7 @@ public class WebUserContext implements SMCredentialsProvider {
this.smSessionId = smAuthInfo.getAuthPermissions().getSessionId();
setUser(authPermissions.getUserId() == null ? null : new WebUser(securityController.getUserById(authPermissions.getUserId())));
}
return isSessionChanged;
}
public synchronized void refreshSMSession() throws DBException {
@@ -72,16 +72,6 @@ public class WebPlatformActivator extends Plugin {
super.stop(context);
}
/**
* Returns configuration file
*/
public static synchronized File getConfigurationFile(String fileName) {
if (configDir == null) {
configDir = getInstance().getStateLocation().toFile();
}
return new File(configDir, fileName);
}
public DBPPreferenceStore getPreferences() {
return preferences;
}
@@ -456,6 +456,11 @@ public class CBApplication extends BaseWebApplication implements WebAuthApplicat
return dataDir.toPath();
}
@Override
public Path getWorkspaceDirectory() {
return Path.of(workspaceLocation);
}
private void initializeSecurityController() throws DBException {
securityController = createGlobalSecurityController();
}
@@ -21,6 +21,7 @@ import io.cloudbeaver.registry.WebDriverRegistry;
import io.cloudbeaver.service.session.WebSessionManager;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
@@ -244,7 +245,7 @@ public class CBPlatform extends BasePlatformImpl {
}
@NotNull
public File getTempFolder(DBRProgressMonitor monitor, String name) {
public Path getTempFolder(DBRProgressMonitor monitor, String name) {
if (tempFolder == null) {
// Make temp folder
monitor.subTask("Create temp folder");
@@ -265,13 +266,12 @@ public class CBPlatform extends BasePlatformImpl {
log.error("Error creating temp folder '" + folder.toAbsolutePath() + "'", e);
}
}
return folder.toFile();
return folder;
}
@NotNull
@Override
public File getConfigurationFile(String fileName) {
return WebPlatformActivator.getConfigurationFile(fileName);
protected Plugin getProductPlugin() {
return WebPlatformActivator.getInstance();
}
@Override
@@ -28,9 +28,9 @@ import org.jkiss.dbeaver.model.struct.DBSDataContainer;
import org.jkiss.dbeaver.utils.ContentUtils;
import org.jkiss.utils.CommonUtils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.List;
@@ -38,7 +38,7 @@ import java.util.List;
public class WebSQLDataLOBReceiver implements DBDDataReceiver {
private static final Log log = Log.getLog(WebSQLDataLOBReceiver.class);
public static final File DATA_EXPORT_FOLDER = CBPlatform.getInstance().getTempFolder(new VoidProgressMonitor(), "sql-lob-files");
public static final Path DATA_EXPORT_FOLDER = CBPlatform.getInstance().getTempFolder(new VoidProgressMonitor(), "sql-lob-files");
private final String tableName;
private final DBSDataContainer dataContainer;
@@ -51,8 +51,12 @@ public class WebSQLDataLOBReceiver implements DBDDataReceiver {
this.tableName = tableName;
this.dataContainer = dataContainer;
this.rowIndex = rowIndex;
if (!DATA_EXPORT_FOLDER.exists()){
DATA_EXPORT_FOLDER.mkdirs();
if (!Files.exists(DATA_EXPORT_FOLDER)){
try {
Files.createDirectories(DATA_EXPORT_FOLDER);
} catch (IOException e) {
log.error("Error creating temp folder", e);
}
}
}
@@ -81,8 +85,8 @@ public class WebSQLDataLOBReceiver implements DBDDataReceiver {
throw new DBQuotaException(
"Data export quota exceeded", CBConstants.QUOTA_PROP_FILE_LIMIT, fileSizeLimit.longValue(), binaryValue.length);
}
File file = new File(DATA_EXPORT_FOLDER, exportFileName);
Files.write(file.toPath(), binaryValue);
Path file = DATA_EXPORT_FOLDER.resolve(exportFileName);
Files.write(file, binaryValue);
return exportFileName;
}
@@ -17,11 +17,10 @@ import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
import java.util.regex.Pattern;
@@ -29,7 +28,7 @@ import java.util.regex.Pattern;
public class WebSQLResultServlet extends WebServiceServletBase {
private static final Log log = Log.getLog(WebSQLResultServlet.class);
private static final MultipartConfigElement MULTI_PART_CONFIG = new MultipartConfigElement(WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER.getAbsolutePath());
private static final MultipartConfigElement MULTI_PART_CONFIG = new MultipartConfigElement(WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER.toAbsolutePath().toString());
// context-id/result-id/row-number/attribute-name
private static final Pattern URL_PATTERN = Pattern.compile("/?([\\w]+)/([0-9]+)/([0-9]+)/([0-9]+)/(.+)[/\\?]?");
@@ -68,18 +67,18 @@ public class WebSQLResultServlet extends WebServiceServletBase {
valuePath = valuePath.substring(1);
}
File dataFile = new File(WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER, valuePath);
Path dataFile = WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER.resolve(valuePath);
session.addInfoMessage("Download LOB file ...");
response.setHeader("Content-Type", "application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + dataFile.getName() + "\"");
response.setHeader("Content-Length", String.valueOf(dataFile.length()));
response.setHeader("Content-Disposition", "attachment; filename=\"" + dataFile.getFileName().toString() + "\"");
response.setHeader("Content-Length", String.valueOf(Files.size(dataFile)));
response.setDateHeader("Expires", System.currentTimeMillis() + CBStaticServlet.STATIC_CACHE_SECONDS * 1000);
response.setHeader("Cache-Control", "public, max-age=" + CBStaticServlet.STATIC_CACHE_SECONDS);
try (InputStream is = new FileInputStream(dataFile)) {
try (InputStream is = Files.newInputStream(dataFile)) {
IOUtils.copyStream(is, response.getOutputStream());
}
Files.deleteIfExists(dataFile.toPath());
Files.deleteIfExists(dataFile);
}
}
}
@@ -39,9 +39,9 @@ import org.jkiss.utils.Base64;
import org.jkiss.utils.CommonUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.*;
/**
@@ -211,7 +211,7 @@ public class WebSQLUtils {
case WebSQLConstants.VALUE_TYPE_CONTENT: {
if (map.get(WebSQLConstants.ATTR_BINARY) != null) {
DBDContentStorage storage;
File openFile = new File(WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER, (String) map.get("fileName"));
Path openFile = WebSQLDataLOBReceiver.DATA_EXPORT_FOLDER.resolve((String) map.get("fileName"));
Object tempValue = ((DBDAttributeBinding) attribute).getValueHandler().getValueFromObject(
session,
attribute,
@@ -14,10 +14,10 @@ import org.jkiss.utils.IOUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
public class WebDataTransferServlet extends WebServiceServletBase {
@@ -56,13 +56,13 @@ public class WebDataTransferServlet extends WebServiceServletBase {
fileName = taskInfo.getDataFileId();
}
File dataFile = taskInfo.getDataFile();
Path dataFile = taskInfo.getDataFile();
session.addInfoMessage("Download data ...");
response.setHeader("Content-Type", processor.getContentType());
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
response.setHeader("Content-Length", String.valueOf(dataFile.length()));
response.setHeader("Content-Length", String.valueOf(Files.size(dataFile)));
try (InputStream is = new FileInputStream(dataFile)) {
try (InputStream is = Files.newInputStream(dataFile)) {
IOUtils.copyStream(is, response.getOutputStream());
}
@@ -2,27 +2,29 @@ package io.cloudbeaver.service.data.transfer.impl;
import org.jkiss.dbeaver.Log;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class WebDataTransferTaskConfig {
private static final Log log = Log.getLog(WebDataTransferTaskConfig.class);
private File dataFile;
private Path dataFile;
private WebDataTransferParameters parameters;
private String exportFileName;
public WebDataTransferTaskConfig(File dataFile, WebDataTransferParameters parameters) {
public WebDataTransferTaskConfig(Path dataFile, WebDataTransferParameters parameters) {
this.dataFile = dataFile;
this.parameters = parameters;
}
public File getDataFile() {
public Path getDataFile() {
return dataFile;
}
public String getDataFileId() {
return dataFile.getName();
return dataFile.getFileName().toString();
}
public WebDataTransferParameters getParameters() {
@@ -38,8 +40,10 @@ public class WebDataTransferTaskConfig {
}
public void deleteFile() {
if (!dataFile.delete()) {
log.error("Error deleting export file " + dataFile.getAbsolutePath());
try {
Files.delete(dataFile);
} catch (IOException e) {
log.error("Error deleting export file " + dataFile.toAbsolutePath(), e);
}
}
}
@@ -51,9 +51,10 @@ import org.jkiss.dbeaver.tools.transfer.stream.StreamTransferConsumer;
import org.jkiss.dbeaver.utils.ContentUtils;
import org.jkiss.utils.CommonUtils;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
@@ -66,21 +67,19 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer {
private static final Log log = Log.getLog(WebServiceDataTransfer.class);
private final File dataExportFolder;
private final Path dataExportFolder;
public WebServiceDataTransfer() {
dataExportFolder = CBPlatform.getInstance().getTempFolder(new VoidProgressMonitor(), "data-transfer");
ContentUtils.deleteFileRecursive(dataExportFolder);
if (!dataExportFolder.mkdirs()) {
log.error("Error re-creating temporary folder");
try {
Files.createDirectories(dataExportFolder);
} catch (IOException e) {
log.error("Error re-creating temporary folder", e);
}
}
public File getDataExportFolder() {
return dataExportFolder;
}
@Override
public List<WebDataTransferStreamProcessor> getAvailableStreamProcessors(WebSession session) {
List<DataTransferProcessorDescriptor> processors = DataTransferRegistry.getInstance().getAvailableProcessors(StreamTransferConsumer.class, DBSEntity.class);
@@ -130,10 +129,12 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer {
if (taskInfo == null) {
throw new DBWebException("Session task '" + dataFileId + "' not found");
}
File dataFile = taskInfo.getDataFile();
Path dataFile = taskInfo.getDataFile();
if (dataFile != null) {
if (!dataFile.delete()) {
log.warn("Error deleting data file '" + dataFile.getAbsolutePath() + "'");
try {
Files.delete(dataFile);
} catch (IOException e) {
log.warn("Error deleting data file '" + dataFile.toAbsolutePath() + "'", e);
}
}
dtConfig.removeTask(taskInfo);
@@ -151,13 +152,15 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer {
monitor.beginTask("Export data", 1);
try {
monitor.subTask("Export data using " + processor.getName());
File exportFile = new File(dataExportFolder, makeUniqueFileName(sqlProcessor, processor));
Path exportFile = dataExportFolder.resolve(makeUniqueFileName(sqlProcessor, processor));
try {
exportData(monitor, processor, dataContainer, parameters, resultsInfo, exportFile);
} catch (Exception e) {
if (exportFile.exists()) {
if (!exportFile.delete()) {
log.error("Error deleting export file " + exportFile.getAbsolutePath());
if (Files.exists(exportFile)) {
try {
Files.delete(exportFile);
} catch (IOException ex) {
log.error("Error deleting export file " + exportFile.toAbsolutePath(), e);
}
}
if (e instanceof DBException) {
@@ -170,7 +173,7 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer {
taskConfig.setExportFileName(exportFileName);
WebDataTransferUtils.getSessionDataTransferConfig(sqlProcessor.getWebSession()).addTask(taskConfig);
result = exportFile.getName();
result = exportFile.getFileName().toString();
} catch (Throwable e) {
throw new InvocationTargetException(e);
} finally {
@@ -187,7 +190,7 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer {
DBSDataContainer dataContainer,
WebDataTransferParameters parameters,
WebSQLResultsInfo resultsInfo,
File exportFile) throws DBException, IOException
Path exportFile) throws DBException, IOException
{
IDataTransferProcessor processorInstance = processor.getInstance();
if (!(processorInstance instanceof IStreamDataExporter)) {
@@ -211,8 +214,8 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer {
StreamConsumerSettings settings = new StreamConsumerSettings();
settings.setOutputEncodingBOM(false);
settings.setOutputFolder(exportFile.getParentFile().getAbsolutePath());
settings.setOutputFilePattern(exportFile.getName());
settings.setOutputFolder(exportFile.getParent().toAbsolutePath().toString());
settings.setOutputFilePattern(exportFile.getFileName().toString());
Map<String, Object> properties = new HashMap<>();
@@ -116,8 +116,9 @@ export const Loader = observer<Props>(function Loader({
if (loading) {
if (element.cancel) {
const cancelCopy = onCancel;
onCancel = () => {
onCancel?.();
cancelCopy?.();
element.cancel?.();
};
}
@@ -54,6 +54,7 @@ export interface INotification<TProps extends INotificationExtraProps<any> = INo
message?: string;
timestamp: number;
details?: string | Error | null;
autoClose?: boolean;
persistent?: boolean;
state: { deleteDelay: number };
isSilent: boolean;
@@ -69,6 +70,7 @@ export interface INotificationOptions<TProps extends INotificationExtraProps<any
message?: string;
details?: string | Error | null;
isSilent?: boolean;
autoClose?: boolean;
persistent?: boolean;
extraProps?: TProps;
timestamp?: number;
@@ -80,6 +80,7 @@ export class NotificationService {
isSilent: !!options.isSilent,
customComponent: options.customComponent,
extraProps: options.extraProps || {} as TProps,
autoClose: options.autoClose,
persistent: options.persistent,
state: observable({ deleteDelay: 0 }),
timestamp: options.timestamp || Date.now(),
@@ -22,7 +22,7 @@ export class NotificationItemController implements IInitializableController {
isDetailsDialogOpen = false;
private notification!: INotification<any>;
constructor(private commonDialogService: CommonDialogService) {
constructor(private readonly commonDialogService: CommonDialogService) {
makeObservable(this, {
isDetailsDialogOpen: observable,
});
@@ -35,7 +35,11 @@ export class NotificationItemController implements IInitializableController {
this.handleShowDetails = this.showDetails.bind(this);
}
if (notification.type !== ENotificationType.Error && !notification.persistent) {
if (
notification.type !== ENotificationType.Error
&& !notification.persistent
&& notification.autoClose !== false
) {
this.closeAfter = FadeTimeout;
}
}
@@ -237,9 +237,7 @@ export class ConnectionOptionsTabService extends Bootstrap {
tempConfig.description = state.config.description;
if (state.projectId === PROJECT_GLOBAL_ID) {
tempConfig.template = state.config.template;
}
tempConfig.template = state.projectId === PROJECT_GLOBAL_ID ? state.config.template : false;
tempConfig.driverId = state.config.driverId;
@@ -63,9 +63,9 @@ export class LogViewerService {
toggle(): void {
if (this.isActive) {
this.stopLog();
this.settings.active = false;
} else {
this.startLog();
this.settings.active = true;
}
}
@@ -74,14 +74,14 @@ export class LogViewerService {
}
async startLog(): Promise<void> {
if (this.isActive) {
if (this.timeoutTaskId !== null) {
return;
}
if (!this.isLogViewerAvailable()) {
throw new Error('Access denied');
}
this.failedRequestsCount = 0;
this.settings.active = true;
const refreshInterval = this.logViewerSettingsService.settings.isValueDefault('refreshTimeout')
? this.coreSettingsService.settings.getValue('app.logViewer.refreshTimeout')
@@ -100,7 +100,6 @@ export class LogViewerService {
clearTimeout(this.timeoutTaskId);
this.timeoutTaskId = null;
}
this.settings.active = false;
}
clearLog(): void {
@@ -7,6 +7,7 @@
*/
import { observable } from 'mobx';
import { useEffect } from 'react';
import { useObjectRef, useObservableRef } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
@@ -22,6 +23,13 @@ interface Props {
export function useLogViewer() {
const logViewerService = useService(LogViewerService);
useEffect(() => {
logViewerService.startLog();
return () => {
logViewerService.stopLog();
};
}, []);
const props: Props = useObservableRef(
() => ({ selectedItem: null }),
{ selectedItem: observable.ref },
@@ -204,7 +204,7 @@ export class PluginBootstrap extends Bootstrap {
this.notificationService.logInfo({
title: 'sql_editor_upload_script_max_size_title',
message: `Max size: ${maxSize}KB\nFile size: ${size}KB`,
persistent: true,
autoClose: false,
});
return;
@@ -82,6 +82,7 @@ export function useTools(state: ISqlEditorTabState): Readonly<State> {
this.notificationService.logInfo({
title: 'sql_editor_upload_script_max_size_title',
message: `Max size: ${maxSize}KB\nFile size: ${size}KB`,
autoClose: false,
});
return false;