diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java index ca3921cd3e..a66f9cdf15 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java @@ -607,11 +607,13 @@ public List findTasksByJob(@NotNull Class runnable) { WebAsyncTaskInfo asyncTask = createAsyncTask(taskName); return runAsyncTask(asyncTask, runnable); } + @NotNull public WebAsyncTaskInfo runAsyncTask(@NotNull WebAsyncTaskInfo asyncTask, @NotNull WebAsyncTaskProcessor runnable) { AbstractJob job = new AbstractCancelableJob(asyncTask.getName()) { @NotNull diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBClientEventProcessor.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBClientEventProcessor.java index 08eb1f97e9..0bb70b84a5 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBClientEventProcessor.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBClientEventProcessor.java @@ -25,6 +25,8 @@ import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.model.websocket.WSUtils; import org.jkiss.dbeaver.model.websocket.event.WSClientEvent; +import org.jkiss.dbeaver.model.websocket.registry.WSClientEventDescriptor; +import org.jkiss.dbeaver.model.websocket.registry.WSEventRegistry; import org.jkiss.utils.CommonUtils; public class CBClientEventProcessor { @@ -50,6 +52,17 @@ public void process(@Nullable String message) { return; } + // Handle with custom handlers + WSClientEventDescriptor ced = WSEventRegistry.getInstance().getClientEvent(clientEvent.getId()); + if (ced != null && ced.getHandler() != null) { + try { + ced.getHandler().handleEvent(webSession, clientEvent); + } catch (Exception e) { + log.error("Error handling event '" + clientEvent.getId() + "'", e); + } + return; + } + switch (clientEvent.getId()) { case WSSubscribeOnTopicClientEvent.ID: { webSession.getEventsFilter().subscribeOnEventTopic(clientEvent.getTopicId()); diff --git a/webapp/packages/core-blocks/src/Expand/Expandable.tsx b/webapp/packages/core-blocks/src/Expand/Expandable.tsx index 90f86f3268..d4ec6489b0 100644 --- a/webapp/packages/core-blocks/src/Expand/Expandable.tsx +++ b/webapp/packages/core-blocks/src/Expand/Expandable.tsx @@ -9,27 +9,28 @@ import { observer } from 'mobx-react-lite'; import { type ReactNode } from 'react'; import { IconOrImage } from '../IconOrImage.js'; -import { DisclosureProvider, Disclosure, DisclosureContent } from '@dbeaver/ui-kit'; +import { DisclosureProvider, Disclosure, DisclosureContent, clsx } from '@dbeaver/ui-kit'; import './Expandable.css'; interface Props { - label: string; + label: string | ReactNode; children: ReactNode; defaultExpanded?: boolean; disabled?: boolean; + className?: string; } -export const Expandable = observer(function Expandable({ label, defaultExpanded, disabled, children }: Props) { +export const Expandable = observer(function Expandable({ label, defaultExpanded, disabled, children, className }: Props) { return (
-

{label}

+ {typeof label === 'string' ?

{label}

: label}
-
{children}
+
{children}
diff --git a/webapp/packages/core-root/src/SessionEventSource.ts b/webapp/packages/core-root/src/SessionEventSource.ts index 439e6a9a7c..4ba360e488 100644 --- a/webapp/packages/core-root/src/SessionEventSource.ts +++ b/webapp/packages/core-root/src/SessionEventSource.ts @@ -47,9 +47,9 @@ export { ServerEventId, SessionEventTopic, ClientEventId }; export type SessionEventId = ServerEventId | ClientEventId | string; -export interface ISessionEvent extends IBaseServerEvent { +export interface ISessionEvent extends IBaseServerEvent { id: SessionEventId; - topicId?: SessionEventTopic; + topicId?: T; [key: string]: any; }