From 26e6cd28c266780952c263b13457a2044f53d579 Mon Sep 17 00:00:00 2001 From: Alex Ma Date: Mon, 14 Mar 2022 09:44:09 -0700 Subject: [PATCH] Add account loading screen until provider accounts have finished loading (#18692) * Added wait for accounts to be loaded to prevent premature loading * revert changes * WIP loading screen * added work in progress emitter. * added test event fire * added test for accountDialogController emitter * fixed test * added event emitters inside accountDialog * WIP changes to loading * added fixed filter removed unnecessary emitters * added working loading page * fix for spaces * added improvements * fixed space * added loading provider label xlf * moved spinner = false to show views * Added loadingSpinner * removed additional localization * removed change to css * removed newline * small changes * fixed spaces * fixed line positions * removed loadingComplete * added spinner container (so that account loading spinner appears on top) * added small fix * changed wording * changed wording slightly * removed comment --- .../browser/accountDialogController.test.ts | 2 +- .../browser/accountDialog.ts | 32 +++++++++++++++---- .../browser/accountManagementService.ts | 4 +-- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/sql/workbench/contrib/accounts/test/browser/accountDialogController.test.ts b/src/sql/workbench/contrib/accounts/test/browser/accountDialogController.test.ts index 163873c263..acb0ae448f 100644 --- a/src/sql/workbench/contrib/accounts/test/browser/accountDialogController.test.ts +++ b/src/sql/workbench/contrib/accounts/test/browser/accountDialogController.test.ts @@ -87,7 +87,7 @@ function createInstantiationService(addAccountFailureEmitter?: Emitter): .returns(() => undefined); // Create a mock account dialog - let accountDialog = new AccountDialog(undefined!, undefined!, instantiationService.object, undefined!, undefined!, undefined!, undefined!, new MockContextKeyService(), undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!); + let accountDialog = new AccountDialog(undefined!, undefined!, instantiationService.object, undefined!, undefined!, undefined!, undefined!, new MockContextKeyService(), undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!); let mockAccountDialog = TypeMoq.Mock.ofInstance(accountDialog); mockAccountDialog.setup(x => x.onAddAccountErrorEvent) .returns(() => { return addAccountFailureEmitter ? addAccountFailureEmitter.event : mockEvent.event; }); diff --git a/src/sql/workbench/services/accountManagement/browser/accountDialog.ts b/src/sql/workbench/services/accountManagement/browser/accountDialog.ts index 2d510e9bea..5f0d062b2c 100644 --- a/src/sql/workbench/services/accountManagement/browser/accountDialog.ts +++ b/src/sql/workbench/services/accountManagement/browser/accountDialog.ts @@ -45,7 +45,9 @@ import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { Iterable } from 'vs/base/common/iterator'; +import { LoadingSpinner } from 'sql/base/browser/ui/loadingSpinner/loadingSpinner'; import { Tenant, TenantListDelegate, TenantListRenderer } from 'sql/workbench/services/accountManagement/browser/tenantListRenderer'; +import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces'; export const VIEWLET_ID = 'workbench.view.accountpanel'; @@ -130,6 +132,7 @@ export class AccountDialog extends Modal { // MEMBER VARIABLES //////////////////////////////////////////////////// private _providerViewsMap = new Map(); + private _loadingSpinner: LoadingSpinner; private _closeButton?: Button; private _addAccountButton?: Button; @@ -161,7 +164,8 @@ export class AccountDialog extends Modal { @IQuickInputService private _quickInputService: IQuickInputService, @INotificationService private _notificationService: INotificationService, @IOpenerService protected readonly openerService: IOpenerService, - @ITelemetryService private readonly vstelemetryService: ITelemetryService + @ITelemetryService private readonly vstelemetryService: ITelemetryService, + @IAccountManagementService private readonly _accountManagementService: IAccountManagementService, ) { super( localize('linkedAccounts', "Linked accounts"), @@ -172,8 +176,7 @@ export class AccountDialog extends Modal { themeService, logService, textResourcePropertiesService, - contextKeyService, - { hasSpinner: true } + contextKeyService ); // Setup the event emitters @@ -209,6 +212,9 @@ export class AccountDialog extends Modal { protected renderBody(container: HTMLElement) { this._container = container; + + this._loadingSpinner = new LoadingSpinner(this._container, { showText: true, fullSize: true }); + this._splitViewContainer = DOM.$('div.account-view.monaco-pane-view'); DOM.append(container, this._splitViewContainer); this._splitView = new SplitView(this._splitViewContainer); @@ -252,23 +258,37 @@ export class AccountDialog extends Modal { this.hide(hideReason); } - public open() { + public async open() { + let accountMetadata = await this._accountManagementService.getAccountProviderMetadata(); this.show(); if (!this.isEmptyLinkedAccount()) { this.showSplitView(); - } else { + } + else if (accountMetadata.length === 0) { + this.showLoadingSpinner(); + } + else { this.showNoAccountContainer(); } } private showNoAccountContainer() { + this._loadingSpinner.loading = false; this._splitViewContainer!.hidden = true; this._noaccountViewContainer!.hidden = false; this._addAccountButton!.focus(); } + private showLoadingSpinner() { + this._loadingSpinner.loadingMessage = localize('accountDialog.loadingProviderLabel', "Loading accounts..."); + this._loadingSpinner.loading = true; + this._splitViewContainer!.hidden = true; + this._noaccountViewContainer!.hidden = true; + } + private showSplitView() { + this._loadingSpinner.loading = false; this._splitViewContainer!.hidden = false; this._noaccountViewContainer!.hidden = true; if (Iterable.consume(this._providerViewsMap.values()).length > 0) { @@ -318,9 +338,7 @@ export class AccountDialog extends Modal { AddAccountAction, newProvider.addedProvider.id ); - addAccountAction.addAccountCompleteEvent(() => this.spinner = false); addAccountAction.addAccountErrorEvent(msg => this._onAddAccountErrorEmitter.fire(msg)); - addAccountAction.addAccountStartEvent(() => this.spinner = true); let providerView = new AccountPanel( { diff --git a/src/sql/workbench/services/accountManagement/browser/accountManagementService.ts b/src/sql/workbench/services/accountManagement/browser/accountManagementService.ts index d3003281bc..954ec84387 100644 --- a/src/sql/workbench/services/accountManagement/browser/accountManagementService.ts +++ b/src/sql/workbench/services/accountManagement/browser/accountManagementService.ts @@ -377,8 +377,8 @@ export class AccountManagementService implements IAccountManagementService { const accounts = await this._accountStore.getAccountsByProvider(providerMetadata.id); const updatedAccounts = await provider.initialize(accounts); - // Don't add the accounts that are about to get deleted to the cache. - this._providers[providerMetadata.id].accounts = updatedAccounts.filter(s => s.delete === false); + // Don't add the accounts that are explicitly marked to be deleted to the cache. + this._providers[providerMetadata.id].accounts = updatedAccounts.filter(s => !s.delete); const writePromises = updatedAccounts.map(async (account) => { if (account.delete === true) {