fix: CB-591 updating tabs after changing connections

This commit is contained in:
Wroud
2020-12-08 22:30:24 +03:00
parent d22349f9dc
commit 1277129797
8 changed files with 68 additions and 33 deletions
@@ -51,10 +51,7 @@ export class ConnectionsAdministrationService extends Bootstrap {
onActivate: this.loadConnections.bind(this),
onDeActivate: async (configuration: boolean, outside: boolean) => {
if (outside) {
const updated = await this.connectionsResource.updateSessionConnections();
if (updated) {
await this.connectionInfoResource.refreshSession();
}
await this.connectionInfoResource.refreshSession();
}
},
});
@@ -17,9 +17,12 @@ import {
GraphQLService,
CachedMapResource,
ConnectionConfig,
UserConnectionAuthPropertiesFragment
UserConnectionAuthPropertiesFragment,
resourceKeyList
} from '@cloudbeaver/core-sdk';
import { ConnectionsResource } from './Administration/ConnectionsResource';
export type Connection = UserConnectionFragment & { authProperties?: UserConnectionAuthPropertiesFragment[] };
@injectable()
@@ -29,6 +32,7 @@ export class ConnectionInfoResource extends CachedMapResource<string, Connection
private sessionUpdate: boolean;
constructor(
private graphQLService: GraphQLService,
private connectionsResource: ConnectionsResource,
appAuthService: AppAuthService,
sessionResource: SessionResource
) {
@@ -42,28 +46,39 @@ export class ConnectionInfoResource extends CachedMapResource<string, Connection
// it's prevents double nav tree refresh
this.onItemAdd.addHandler(() => !this.sessionUpdate);
this.onItemDelete.addHandler(() => !this.sessionUpdate);
this.onConnectionCreate.addHandler(() => !this.sessionUpdate);
sessionResource.onDataOutdated.addHandler(() => this.markOutdated());
appAuthService.auth.addHandler(() => this.refreshSession(true));
}
@action async refreshSession(sessionUpdate?: boolean): Promise<void> {
this.sessionUpdate = true;
this.sessionUpdate = sessionUpdate === true;
try {
const { state: { connections } } = await this.graphQLService.sdk.getSessionConnections();
const connectionsList = resourceKeyList(Array.from(this.data.keys()));
await this.performUpdate(connectionsList, async () => {
if (!sessionUpdate) {
const updated = await this.connectionsResource.updateSessionConnections();
const restoredConnections = new Set<string>();
for (const connection of connections) {
await this.add(connection, sessionUpdate);
restoredConnections.add(connection.id);
}
if (!updated) {
return;
}
}
const unrestoredConnectionIdList = Array.from(this.data.values())
.map(connection => connection.id)
.filter(connectionId => !restoredConnections.has(connectionId));
const { state: { connections } } = await this.graphQLService.sdk.getSessionConnections();
for (const connectionId of unrestoredConnectionIdList) {
this.delete(connectionId);
}
const restoredConnections = new Set<string>();
for (const connection of connections) {
await this.add(connection);
restoredConnections.add(connection.id);
}
const unrestoredConnectionIdList = Array.from(this.data.values())
.map(connection => connection.id)
.filter(connectionId => !restoredConnections.has(connectionId));
this.delete(resourceKeyList(unrestoredConnectionIdList));
});
} finally {
this.sessionUpdate = false;
}
@@ -87,13 +102,13 @@ export class ConnectionInfoResource extends CachedMapResource<string, Connection
return this.add(connection);
}
@action async add(connection: Connection, update?: boolean): Promise<Connection> {
@action async add(connection: Connection): Promise<Connection> {
const exists = this.data.has(connection.id);
this.set(connection.id, connection);
const observedConnection = this.get(connection.id)!;
if (!update && !exists) {
if (!exists) {
await this.onConnectionCreate.execute(observedConnection);
}
@@ -104,7 +119,6 @@ export class ConnectionInfoResource extends CachedMapResource<string, Connection
await this.performUpdate(id, async () => {
const connection = await this.initConnection(id, credentials, saveCredentials);
this.set(id, connection);
return connection;
});
return this.get(id)!;
@@ -22,12 +22,14 @@ export function useConnectionInfo(connectionId: string) {
const refresh = useCallback(() => service.refresh(connectionId), [service, connectionId]);
const isLoading = useCallback(() => service.isDataLoading(connectionId), [service, connectionId]);
const isLoaded = useCallback(() => service.isLoaded(connectionId), [service, connectionId]);
const isOutdated = useCallback(() => service.isOutdated(connectionId), [service, connectionId]);
const connect = useCallback(() => manager.requireConnection(connectionId), [manager, connectionId]);
return {
connectionInfo,
isLoading,
isLoaded,
isOutdated,
load,
refresh,
connect,
@@ -47,6 +47,16 @@ export class TaskScheduler<TIdentifier> {
}
}
async wait(): Promise<void> {
const queueList = this.queue.slice();
for (const task of queueList) {
try {
await task.task;
} catch {}
}
}
private async scheduler<T>(id: TIdentifier, promise: () => Promise<T>) {
if (!this.isBlocked) {
return promise();
@@ -49,6 +49,10 @@ export abstract class CachedResource<
abstract isLoaded(param: TParam): boolean;
waitLoad(): Promise<void> {
return this.scheduler.wait();
}
isLoading(): boolean {
return this.loading;
}
@@ -26,11 +26,6 @@ export class ResourceKeyList<TKey> {
}
}
interface ForeachFnc {
<TKey>(key: ResourceKey<TKey>, action: (key: TKey, index: number) => any): any;
<TKey>(key: ResourceKey<TKey>, action: (key: TKey, index: number) => Promise<any>): Promise<any>;
}
interface MapFnc {
<TKey, TValue>(key: ResourceKeyList<TKey>, selector: (key: TKey, index: number) => TValue): TValue[];
<TKey, TValue>(
@@ -59,12 +59,18 @@ export const ObjectViewerPanel = observer(function ObjectViewerPanel({
navigation.selectTab(tab.id);
}, [navigation, connection, tab]);
if (connection.connectionInfo && !connection.connectionInfo.connected && !connection.isLoading()) {
return (
<TextPlaceholder>
<Button type="button" mod={['unelevated']} onClick={handleConnect}>{translate('connections_connection_connect')}</Button>
</TextPlaceholder>
);
if (connection.connectionInfo) {
if (connection.isLoading()) {
return <Loader />;
}
if (!connection.connectionInfo.connected) {
return (
<TextPlaceholder>
<Button type="button" mod={['unelevated']} onClick={handleConnect}>{translate('connections_connection_connect')}</Button>
</TextPlaceholder>
);
}
}
if (!isLoaded() || (!isOutdated() && isLoading())) {
@@ -190,7 +190,7 @@ export class ObjectViewerTabService {
);
if (tab) {
if (tab.handlerState.connectionId) {
if (tab.handlerState.connectionId && this.connectionInfo.has(tab.handlerState.connectionId)) {
const connection = await this.connectionInfo.load(tab.handlerState.connectionId);
if (!connection.connected) {
@@ -229,6 +229,13 @@ export class ObjectViewerTabService {
private async selectObjectTab(tab: ITab<IObjectViewerTabState>) {
try {
if (tab.handlerState.connectionId) {
// here we wait when connections info will be updated and then check is connections is steel available
await this.connectionInfo.waitLoad();
if (!this.connectionInfo.has(tab.handlerState.connectionId)) {
return;
}
const connection = await this.connectionInfo.load(tab.handlerState.connectionId);
if (!connection.connected) {