Skip to content

Commit

Permalink
CB-4707 move connection shield logic to separate component (#2478)
Browse files Browse the repository at this point in the history
* CB-4707 move connection shield logic to separate component

* CB-4707 use lazy import

* CB-4707 revert interface

---------

Co-authored-by: mr-anton-t <[email protected]>
  • Loading branch information
devnaumov and mr-anton-t authored Mar 22, 2024
1 parent e9163b8 commit affbe44
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const DEFAULT_NAVIGATOR_VIEW_SETTINGS: NavigatorSettingsInput = {
@injectable()
export class ConnectionInfoResource extends CachedMapResource<IConnectionInfoParams, Connection, ConnectionInfoIncludes> {
readonly onConnectionCreate: ISyncExecutor<Connection>;
readonly onConnectionClose: ISyncExecutor<Connection>;
readonly onConnectionClose: ISyncExecutor<IConnectionInfoParams>;

private sessionUpdate: boolean;
private readonly nodeIdMap: Map<string, IConnectionInfoParams>;
Expand Down Expand Up @@ -445,7 +445,7 @@ export class ConnectionInfoResource extends CachedMapResource<IConnectionInfoPar
});

const connection = this.get(key)!;
this.onConnectionClose.execute(connection);
this.onConnectionClose.execute(key);
return connection;
}

Expand Down
60 changes: 60 additions & 0 deletions webapp/packages/plugin-connections/src/ConnectionShield.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { observer } from 'mobx-react-lite';
import { type PropsWithChildren, useState } from 'react';

import { Button, Loader, TextPlaceholder, useResource, useTranslate } from '@cloudbeaver/core-blocks';
import { ConnectionInfoResource, ConnectionsManagerService, type IConnectionInfoParams } from '@cloudbeaver/core-connections';
import { useService } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';

export interface IConnectionShieldProps {
connectionKey: IConnectionInfoParams | null;
}

export const ConnectionShield = observer<PropsWithChildren<IConnectionShieldProps>>(function ConnectionShield({ connectionKey, children }) {
const translate = useTranslate();
const connectionsManagerService = useService(ConnectionsManagerService);
const notificationService = useService(NotificationService);

const connection = useResource(ConnectionShield, ConnectionInfoResource, connectionKey);

const [connecting, setConnecting] = useState(false);

async function handleConnect() {
if (connecting || !connection.data || !connectionKey) {
return;
}

setConnecting(true);

try {
await connectionsManagerService.requireConnection(connectionKey);
} catch (exception: any) {
notificationService.logException(exception);
} finally {
setConnecting(false);
}
}

if (connection.data && !connection.data.connected) {
if (connecting || connection.isLoading()) {
return <Loader />;
}

return (
<TextPlaceholder>
<Button type="button" mod={['unelevated']} onClick={handleConnect}>
{translate('connections_connection_connect')}
</Button>
</TextPlaceholder>
);
}

return children;
});
10 changes: 10 additions & 0 deletions webapp/packages/plugin-connections/src/ConnectionShieldLazy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { importLazyComponent } from '@cloudbeaver/core-blocks';

export const ConnectionShieldLazy = importLazyComponent(() => import('./ConnectionShield').then(m => m.ConnectionShield));
1 change: 1 addition & 0 deletions webapp/packages/plugin-connections/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ export * from './ContextMenu/MENU_CONNECTIONS';
export * from './PublicConnectionForm/PublicConnectionFormService';
export * from './ConnectionAuthService';
export * from './PluginConnectionsSettingsService';
export * from './ConnectionShieldLazy';

export default connectionPlugin;
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,16 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { observable, runInAction } from 'mobx';
import { runInAction } from 'mobx';
import { observer } from 'mobx-react-lite';
import { useCallback } from 'react';

import {
Button,
Loader,
s,
SContext,
StyleRegistry,
TextPlaceholder,
useObservableRef,
useResource,
useS,
useTranslate,
} from '@cloudbeaver/core-blocks';
import { ConnectionInfoResource, ConnectionsManagerService } from '@cloudbeaver/core-connections';
import { s, SContext, StyleRegistry, TextPlaceholder, useResource, useS, useTranslate } from '@cloudbeaver/core-blocks';
import { ConnectionInfoResource } from '@cloudbeaver/core-connections';
import { useService } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import { NavNodeInfoResource } from '@cloudbeaver/core-navigation-tree';
import { TabPanel, TabsBox, TabStyles, useTabLocalState } from '@cloudbeaver/core-ui';
import { MetadataMap } from '@cloudbeaver/core-utils';
import { ConnectionShieldLazy } from '@cloudbeaver/plugin-connections';
import type { TabHandlerPanelComponent } from '@cloudbeaver/plugin-navigation-tabs';

import type { IObjectViewerTabState } from '../IObjectViewerTabState';
Expand All @@ -49,27 +37,13 @@ const tabsRegistry: StyleRegistry = [
export const ObjectViewerPanel: TabHandlerPanelComponent<IObjectViewerTabState> = observer(function ObjectViewerPanel({ tab }) {
const translate = useTranslate();
const dbObjectPagesService = useService(DBObjectPageService);
const connectionsManagerService = useService(ConnectionsManagerService);
const navNodeInfoResource = useService(NavNodeInfoResource);
const notificationService = useService(NotificationService);
const innerTabState = useTabLocalState(() => new MetadataMap<string, any>());
const style = useS(styles);

const objectId = tab.handlerState.objectId;
const connectionKey = tab.handlerState.connectionKey || null;

const state = useObservableRef(
() => ({
connecting: false,
notFound: false,
}),
{
connecting: observable.ref,
notFound: observable.ref,
},
false,
);

const connection = useResource(ObjectViewerPanel, ConnectionInfoResource, connectionKey);

const node = useResource(ObjectViewerPanel, navNodeInfoResource, objectId, {
Expand All @@ -79,65 +53,39 @@ export const ObjectViewerPanel: TabHandlerPanelComponent<IObjectViewerTabState>
tab.handlerState.tabTitle = data.name;
});
},
active: !state.notFound && connection.data?.connected,
active: connection.data?.connected,
});

const pages = dbObjectPagesService.orderedPages;

const handleConnect = useCallback(async () => {
if (state.connecting || !connection.data || !connectionKey) {
return;
}

state.connecting = true;

try {
await connectionsManagerService.requireConnection(connectionKey);
} catch (exception: any) {
notificationService.logException(exception);
} finally {
state.connecting = false;
}
}, [connectionKey]);

if (connection.data && !connection.data.connected) {
if (state.connecting || connection.isLoading()) {
return <Loader />;
}

return (
<TextPlaceholder>
<Button type="button" mod={['unelevated']} onClick={handleConnect}>
{translate('connections_connection_connect')}
</Button>
</TextPlaceholder>
);
}

if (tab.handlerState.error || state.notFound) {
if (tab.handlerState.error) {
return <TextPlaceholder>{translate('plugin_object_viewer_error')}</TextPlaceholder>;
}

return node.data ? (
<TabsBox
currentTabId={tab.handlerState.pageId}
tabsClassName={s(style, { tabs: true })}
tabs={
<SContext registry={tabsRegistry}>
return (
<ConnectionShieldLazy connectionKey={connectionKey}>
{node.data ? (
<TabsBox
currentTabId={tab.handlerState.pageId}
tabsClassName={s(style, { tabs: true })}
tabs={
<SContext registry={tabsRegistry}>
{pages.map(page => (
<DBObjectPageTab key={page.key} tab={tab} page={page} onSelect={dbObjectPagesService.selectPage} />
))}
</SContext>
}
localState={innerTabState}
>
{pages.map(page => (
<DBObjectPageTab key={page.key} tab={tab} page={page} onSelect={dbObjectPagesService.selectPage} />
<TabPanel key={page.key} tabId={page.key} lazy>
<DBObjectPagePanel tab={tab} page={page} />
</TabPanel>
))}
</SContext>
}
localState={innerTabState}
>
{pages.map(page => (
<TabPanel key={page.key} tabId={page.key} lazy>
<DBObjectPagePanel tab={tab} page={page} />
</TabPanel>
))}
</TabsBox>
) : (
<TextPlaceholder>{translate('plugin_object_viewer_table_no_items')}</TextPlaceholder>
</TabsBox>
) : (
<TextPlaceholder>{translate('plugin_object_viewer_table_no_items')}</TextPlaceholder>
)}
</ConnectionShieldLazy>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ export class ObjectViewerTabService {
this.navNodeManagerService.onCanOpen.addHandler(this.canOpenHandler.bind(this));
this.navNodeManagerService.navigator.addHandler(this.navigationHandler.bind(this));
this.navNodeManagerService.navigator.addPostHandler(this.navigationPostHandler.bind(this));
this.connectionInfoResource.onConnectionClose.addHandler(this.closeConnectionInfoTabs.bind(this));
this.connectionInfoResource.onItemUpdate.addHandler(this.updateConnectionTabs.bind(this));
this.connectionInfoResource.onConnectionClose.addHandler(this.closeConnectionTabs.bind(this));
this.connectionInfoResource.onItemDelete.addHandler(this.closeConnectionTabs.bind(this));
this.navNodeManagerService.navTree.onItemDelete.addHandler(this.removeTabs.bind(this));
this.navTreeResource.onNodeRename.addHandler(this.handleNodeRename.bind(this));
Expand Down Expand Up @@ -254,21 +254,6 @@ export class ObjectViewerTabService {
});
}

private closeConnectionInfoTabs(connection: Connection) {
if (!connection.connected) {
const tabs = Array.from(
this.navigationTabsService.findTabs(
isObjectViewerTab(
tab =>
tab.handlerState.connectionKey?.projectId === connection.projectId && tab.handlerState.connectionKey.connectionId === connection.id,
),
),
).map(tab => tab.id);

this.navigationTabsService.closeTabSilent(resourceKeyList(tabs), true);
}
}

private async removeTabs(key: ResourceKey<string>) {
const tabs: string[] = [];

Expand Down

0 comments on commit affbe44

Please sign in to comment.