diff --git a/webapp/packages/core-app/src/NavigationTree/NavigationTreeService.ts b/webapp/packages/core-app/src/NavigationTree/NavigationTreeService.ts index 3674ce5d3e..0acfd9ab2e 100644 --- a/webapp/packages/core-app/src/NavigationTree/NavigationTreeService.ts +++ b/webapp/packages/core-app/src/NavigationTree/NavigationTreeService.ts @@ -79,7 +79,7 @@ export class NavigationTreeService { return false; } } - await this.navNodeManagerService.loadTree(id); + await this.navTreeResource.load(id); return true; } catch (exception) { this.notificationService.logException(exception); diff --git a/webapp/packages/core-app/src/NavigationTree/useElementsTree.ts b/webapp/packages/core-app/src/NavigationTree/useElementsTree.ts index 89f1c344da..fe7cd5b01c 100644 --- a/webapp/packages/core-app/src/NavigationTree/useElementsTree.ts +++ b/webapp/packages/core-app/src/NavigationTree/useElementsTree.ts @@ -240,13 +240,13 @@ export function useElementsTree(options: IOptions): IElementsTree { useExecutor({ executor: navNodeInfoResource.onDataOutdated, - handlers: [function refreshRoot() { + postHandlers: [function refreshRoot() { loadTree(options.root); }], }); useExecutor({ executor: navTreeResource.onNodeRefresh, - handlers: [loadTree], + postHandlers: [loadTree], }); useExecutor({ diff --git a/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts b/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts index 7b89fbfdc6..b148304968 100644 --- a/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts +++ b/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts @@ -226,7 +226,7 @@ export class NavTreeResource extends CachedMapResource { private async connectionUpdateHandler(key: ResourceKey) { await this.markOutdated(ROOT_NODE_PATH); - ResourceKeyUtils.forEach(key, async key => { + await ResourceKeyUtils.forEachAsync(key, async key => { const nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(key); if (this.has(nodeId)) { @@ -235,14 +235,14 @@ export class NavTreeResource extends CachedMapResource { if (!connectionInfo?.connected) { this.delete(nodeId); } else { - this.markTreeOutdated(nodeId); + await this.markTreeOutdated(nodeId); } } const node = this.navNodeInfoResource.get(nodeId); if (node) { - this.markOutdated(node.parentId); + await this.markOutdated(node.parentId); } }); } diff --git a/webapp/packages/core-authentication/src/UserInfoResource.ts b/webapp/packages/core-authentication/src/UserInfoResource.ts index 50f5d3d9f5..69afe4132d 100644 --- a/webapp/packages/core-authentication/src/UserInfoResource.ts +++ b/webapp/packages/core-authentication/src/UserInfoResource.ts @@ -59,16 +59,15 @@ export class UserInfoResource extends CachedDataResource } async login(provider: string, credentials: Record, link?: boolean): Promise { - const processedCredentials = await this.authProviderService.processCredentials(provider, credentials); - - const { authToken } = await this.graphQLService.sdk.authLogin({ - provider, - credentials: processedCredentials, - linkUser: link, - customIncludeOriginDetails: true, - }); - await this.performUpdate(undefined, undefined, async () => { + const processedCredentials = await this.authProviderService.processCredentials(provider, credentials); + + const { authToken } = await this.graphQLService.sdk.authLogin({ + provider, + credentials: processedCredentials, + linkUser: link, + customIncludeOriginDetails: true, + }); if (this.data === null || link) { this.data = await this.loader(); } else { diff --git a/webapp/packages/core-sdk/src/Resource/CachedMapResource.ts b/webapp/packages/core-sdk/src/Resource/CachedMapResource.ts index a641e9fb38..a9ccbb25de 100644 --- a/webapp/packages/core-sdk/src/Resource/CachedMapResource.ts +++ b/webapp/packages/core-sdk/src/Resource/CachedMapResource.ts @@ -147,7 +147,7 @@ export abstract class CachedMapResource< markOutdated(key: ResourceKey): Promise async markOutdated(key?: ResourceKey): Promise { if (!key) { - key = resourceKeyList(Array.from(this.data.keys())); + key = resourceKeyList(this.keys); } else { key = this.transformParam(key); } @@ -164,7 +164,7 @@ export abstract class CachedMapResource< markUpdated(key: ResourceKey): void markUpdated(key?: ResourceKey): void { if (!key) { - key = resourceKeyList(Array.from(this.data.keys())); + key = resourceKeyList(this.keys); } else { key = this.transformParam(key); } diff --git a/webapp/packages/core-ui/src/useAuthenticationAction.tsx b/webapp/packages/core-ui/src/useAuthenticationAction.tsx index 7aa41473d1..7fa2a04981 100644 --- a/webapp/packages/core-ui/src/useAuthenticationAction.tsx +++ b/webapp/packages/core-ui/src/useAuthenticationAction.tsx @@ -6,6 +6,8 @@ * you may not use this file except in compliance with the License. */ +import { computed, observable } from 'mobx'; + import { AuthProviderService, UserInfoResource } from '@cloudbeaver/core-authentication'; import { useObjectRef } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; @@ -18,11 +20,12 @@ interface IAuthenticationAction { auth: () => Promise; } interface IAuthenticationData extends IAuthenticationAction { - onAuthenticate?: () => void; + authenticating: boolean; + onAuthenticate?: () => Promise | void; } export type Options = { - onAuthenticate?: () => void; + onAuthenticate?: () => Promise | void; } & ({ origin: ObjectOrigin; } | { @@ -45,19 +48,28 @@ export function useAuthenticationAction(options: Options): IAuthenticationAction } return useObjectRef({ + authenticating: false, type, subType, onAuthenticate: options.onAuthenticate, get authorized() { - return userInfoService.hasToken(this.type, this.subType); + return !this.authenticating && userInfoService.hasToken(this.type, this.subType); }, async auth() { - await authProviderService.requireProvider(this.type, this.subType); - this.onAuthenticate?.(); + this.authenticating = true; + try { + await authProviderService.requireProvider(this.type, this.subType); + await this.onAuthenticate?.(); + } finally { + this.authenticating = false; + } }, }, { type, subType, onAuthenticate: options.onAuthenticate, - }, undefined, ['auth']); + }, { + authorized: computed, + authenticating: observable, + }, ['auth']); }