Code Layering Accounts (#4882)

* code layering for accounts

* formatting

* formatting

* formatting
This commit is contained in:
Anthony Dresser
2019-04-08 14:45:30 -07:00
committed by GitHub
parent ab54f7bb45
commit acc27d0829
48 changed files with 258 additions and 333 deletions

View File

@@ -3,10 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/accountDialog';
import 'vs/css!sql/parts/accountManagement/common/media/accountActions';
import 'vs/css!./media/accountActions';
import * as DOM from 'vs/base/browser/dom';
import { List } from 'vs/base/browser/ui/list/listWidget';
import { Event, Emitter } from 'vs/base/common/event';
@@ -29,10 +27,10 @@ import * as azdata from 'azdata';
import { Button } from 'sql/base/browser/ui/button/button';
import { Modal } from 'sql/workbench/browser/modal/modal';
import { attachModalDialogStyler, attachButtonStyler, attachPanelStyler } from 'sql/platform/theme/common/styler';
import { AccountViewModel } from 'sql/parts/accountManagement/accountDialog/accountViewModel';
import { AddAccountAction } from 'sql/parts/accountManagement/common/accountActions';
import { AccountListRenderer, AccountListDelegate } from 'sql/parts/accountManagement/common/accountListRenderer';
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accountManagement/common/eventTypes';
import { AccountViewModel } from 'sql/platform/accounts/common/accountViewModel';
import { AddAccountAction } from 'sql/platform/accounts/common/accountActions';
import { AccountListRenderer, AccountListDelegate } from 'sql/platform/accounts/browser/accountListRenderer';
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accounts/common/eventTypes';
import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
@@ -149,7 +147,7 @@ export class AccountDialog extends Modal {
// Load the initial contents of the view model
this.viewModel.initialize()
.then(addedProviders => {
for (let addedProvider of addedProviders) {
for (const addedProvider of addedProviders) {
this.addProvider(addedProvider);
}
});
@@ -174,13 +172,13 @@ export class AccountDialog extends Modal {
this._splitView = new SplitView(this._splitViewContainer);
this._noaccountViewContainer = DOM.$('div.no-account-view');
let noAccountTitle = DOM.append(this._noaccountViewContainer, DOM.$('.no-account-view-label'));
let noAccountLabel = localize('accountDialog.noAccountLabel', 'There is no linked account. Please add an account.');
const noAccountTitle = DOM.append(this._noaccountViewContainer, DOM.$('.no-account-view-label'));
const noAccountLabel = localize('accountDialog.noAccountLabel', 'There is no linked account. Please add an account.');
noAccountTitle.innerText = noAccountLabel;
// Show the add account button for the first provider
// Todo: If we have more than 1 provider, need to show all add account buttons for all providers
let buttonSection = DOM.append(this._noaccountViewContainer, DOM.$('div.button-section'));
const buttonSection = DOM.append(this._noaccountViewContainer, DOM.$('div.button-section'));
this._addAccountButton = new Button(buttonSection);
this._addAccountButton.label = localize('accountDialog.addConnection', 'Add an account');
this._register(this._addAccountButton.onDidClick(() => {
@@ -231,7 +229,7 @@ export class AccountDialog extends Modal {
this._splitViewContainer.hidden = false;
this._noaccountViewContainer.hidden = true;
if (values(this._providerViewsMap).length > 0) {
let firstView = values(this._providerViewsMap)[0];
const firstView = values(this._providerViewsMap)[0];
if (firstView instanceof AccountPanel) {
firstView.setSelection([0]);
firstView.focus();
@@ -240,8 +238,8 @@ export class AccountDialog extends Modal {
}
private isEmptyLinkedAccount(): boolean {
for (let provider of values(this._providerViewsMap)) {
let listView = provider.view;
for (const provider of values(this._providerViewsMap)) {
const listView = provider.view;
if (listView && listView.length > 0) {
return false;
}
@@ -251,7 +249,7 @@ export class AccountDialog extends Modal {
public dispose(): void {
super.dispose();
for (let provider of values(this._providerViewsMap)) {
for (const provider of values(this._providerViewsMap)) {
if (provider.addAccountAction) {
provider.addAccountAction.dispose();
}
@@ -317,7 +315,7 @@ export class AccountDialog extends Modal {
private removeProvider(removedProvider: azdata.AccountProviderMetadata) {
// Skip removing the provider if it doesn't exist
let providerView = this._providerViewsMap.get(removedProvider.id);
const providerView = this._providerViewsMap.get(removedProvider.id);
if (!providerView || !providerView.view) {
return;
}
@@ -332,7 +330,7 @@ export class AccountDialog extends Modal {
}
private updateProviderAccounts(args: UpdateAccountListEventParams) {
let providerMapping = this._providerViewsMap.get(args.providerId);
const providerMapping = this._providerViewsMap.get(args.providerId);
if (!providerMapping || !providerMapping.view) {
return;
}

View File

@@ -3,10 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import Severity from 'vs/base/common/severity';
import { AccountDialog } from 'sql/parts/accountManagement/accountDialog/accountDialog';
import { AccountDialog } from 'sql/platform/accounts/browser/accountDialog';
import { localize } from 'vs/nls';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
@@ -28,13 +26,11 @@ export class AccountDialogController {
* Open account dialog
*/
public openAccountDialog(): void {
let self = this;
// Create a new dialog if one doesn't exist
if (!this._accountDialog) {
this._accountDialog = this._instantiationService.createInstance(AccountDialog);
this._accountDialog.onAddAccountErrorEvent(msg => { self.handleOnAddAccountError(msg); });
this._accountDialog.onCloseEvent(() => { self.handleOnClose(); });
this._accountDialog.onAddAccountErrorEvent(msg => this.handleOnAddAccountError(msg));
this._accountDialog.onCloseEvent(() => this.handleOnClose());
this._accountDialog.render();
}

View File

@@ -3,17 +3,17 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!sql/parts/accountManagement/common/media/accountListRenderer';
import 'vs/css!sql/parts/accountManagement/common/media/accountActions';
import 'vs/css!./media/accountListRenderer';
import 'vs/css!./media/accountActions';
import 'vs/css!sql/media/icons/common-icons';
import * as DOM from 'vs/base/browser/dom';
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { ActionBar, IActionOptions } from 'vs/base/browser/ui/actionbar/actionbar';
import { localize } from 'vs/nls';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { RemoveAccountAction, RefreshAccountAction } from 'sql/parts/accountManagement/common/accountActions';
import { RemoveAccountAction, RefreshAccountAction } from 'sql/platform/accounts/common/accountActions';
import * as azdata from 'azdata';
@@ -114,9 +114,9 @@ export class AccountListRenderer extends AccountPickerListRenderer {
}
templateData.actions.clear();
let actionOptions: IActionOptions = { icon: true, label: false };
const actionOptions: IActionOptions = { icon: true, label: false };
if (account.isStale) {
let refreshAction = this._instantiationService.createInstance(RefreshAccountAction);
const refreshAction = this._instantiationService.createInstance(RefreshAccountAction);
refreshAction.account = account;
templateData.actions.push(refreshAction, actionOptions);
} else {
@@ -124,7 +124,7 @@ export class AccountListRenderer extends AccountPickerListRenderer {
// templateData.actions.push(new ApplyFilterAction(ApplyFilterAction.ID, ApplyFilterAction.LABEL), actionOptions);
}
let removeAction = this._instantiationService.createInstance(RemoveAccountAction, account);
const removeAction = this._instantiationService.createInstance(RemoveAccountAction, account);
templateData.actions.push(removeAction, actionOptions);
}
}
}

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/accountListStatusbarItem';
import { Action, IAction } from 'vs/base/common/actions';
import { IDisposable } from 'vs/base/common/lifecycle';
@@ -16,7 +14,7 @@ import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
import { Themable, STATUS_BAR_FOREGROUND } from 'vs/workbench/common/theme';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
export class AccountListStatusbarItem extends Themable implements IStatusbarItem {
private _manageLinkedAccountAction: IAction;
@@ -24,7 +22,6 @@ export class AccountListStatusbarItem extends Themable implements IStatusbarItem
constructor(
@IInstantiationService private _instantiationService: IInstantiationService,
@IAccountManagementService private _accountManagementService: IAccountManagementService,
@IThemeService themeService: IThemeService
) {
super(themeService);

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
@@ -15,7 +13,7 @@ import { join } from 'path';
import { createCSSRule } from 'vs/base/browser/dom';
import { URI } from 'vs/base/common/uri';
import { ManageLinkedAccountAction } from 'sql/parts/accountManagement/accountListStatusbar/accountListStatusbarItem';
import { ManageLinkedAccountAction } from 'sql/platform/accounts/browser/accountListStatusbarItem';
let actionRegistry = <IWorkbenchActionRegistry>Registry.as(Extensions.WorkbenchActions);
@@ -78,10 +76,9 @@ export const accountsContribution: IJSONSchema = {
ExtensionsRegistry.registerExtensionPoint<IAccountContrib | IAccountContrib[]>({ extensionPoint: 'account-type', jsonSchema: accountsContribution }).setHandler(extensions => {
function handleCommand(account: IAccountContrib, extension: IExtensionPointUser<any>) {
let { icon, id } = account;
let iconClass: string;
const { icon, id } = account;
if (icon) {
iconClass = id;
const iconClass = id;
if (typeof icon === 'string') {
const path = join(extension.description.extensionLocation.fsPath, icon);
createCSSRule(`.icon.${iconClass}`, `background-image: url("${URI.file(path).toString()}")`);
@@ -106,4 +103,3 @@ ExtensionsRegistry.registerExtensionPoint<IAccountContrib | IAccountContrib[]>({
}
});

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/accountPicker';
import * as DOM from 'vs/base/browser/dom';
import { Event, Emitter } from 'vs/base/common/event';
@@ -21,9 +20,9 @@ import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import * as azdata from 'azdata';
import { DropdownList } from 'sql/base/browser/ui/dropdownList/dropdownList';
import { attachDropdownStyler } from 'sql/platform/theme/common/styler';
import { AddAccountAction, RefreshAccountAction } from 'sql/parts/accountManagement/common/accountActions';
import { AccountPickerListRenderer, AccountListDelegate } from 'sql/parts/accountManagement/common/accountListRenderer';
import { AccountPickerViewModel } from 'sql/platform/accountManagement/common/accountPickerViewModel';
import { AddAccountAction, RefreshAccountAction } from 'sql/platform/accounts/common/accountActions';
import { AccountPickerListRenderer, AccountListDelegate } from 'sql/platform/accounts/browser/accountListRenderer';
import { AccountPickerViewModel } from 'sql/platform/accounts/common/accountPickerViewModel';
export class AccountPicker extends Disposable {
public static ACCOUNTPICKERLIST_HEIGHT = 47;
@@ -85,8 +84,8 @@ export class AccountPicker extends Disposable {
*/
public createAccountPickerComponent() {
// Create an account list
let delegate = new AccountListDelegate(AccountPicker.ACCOUNTPICKERLIST_HEIGHT);
let accountRenderer = new AccountPickerListRenderer();
const delegate = new AccountListDelegate(AccountPicker.ACCOUNTPICKERLIST_HEIGHT);
const accountRenderer = new AccountPickerListRenderer();
this._listContainer = DOM.$('div.account-list-container');
this._accountList = new List<azdata.Account>(this._listContainer, delegate, [accountRenderer]);
this._register(attachListStyler(this._accountList, this._themeService));
@@ -94,13 +93,13 @@ export class AccountPicker extends Disposable {
this._rootElement = DOM.$('div.account-picker-container');
// Create a dropdown for account picker
let option: IDropdownOptions = {
const option: IDropdownOptions = {
contextViewProvider: this._contextViewService,
labelRenderer: (container) => this.renderLabel(container)
};
// Create the add account action
let addAccountAction = this._instantiationService.createInstance(AddAccountAction, this._providerId);
const addAccountAction = this._instantiationService.createInstance(AddAccountAction, this._providerId);
addAccountAction.addAccountCompleteEvent(() => this._addAccountCompleteEmitter.fire());
addAccountAction.addAccountErrorEvent((msg) => this._addAccountErrorEmitter.fire(msg));
addAccountAction.addAccountStartEvent(() => this._addAccountStartEmitter.fire());
@@ -117,7 +116,7 @@ export class AccountPicker extends Disposable {
// Create refresh account action
this._refreshContainer = DOM.append(this._rootElement, DOM.$('div.refresh-container'));
DOM.append(this._refreshContainer, DOM.$('div.sql icon warning'));
let actionBar = new ActionBar(this._refreshContainer, { animated: false });
const actionBar = new ActionBar(this._refreshContainer, { animated: false });
this._refreshAccountAction = this._instantiationService.createInstance(RefreshAccountAction);
actionBar.push(this._refreshAccountAction, { icon: false, label: true });
@@ -165,8 +164,8 @@ export class AccountPicker extends Disposable {
}
}
let selectedAccounts = this._accountList.getSelectedElements();
let account = selectedAccounts ? selectedAccounts[0] : null;
const selectedAccounts = this._accountList.getSelectedElements();
const account = selectedAccounts ? selectedAccounts[0] : undefined;
if (account) {
const badge = DOM.$('div.badge');
const row = DOM.append(container, DOM.$('div.selected-account-container'));
@@ -190,12 +189,12 @@ export class AccountPicker extends Disposable {
const row = DOM.append(container, DOM.$('div.no-account-container'));
row.innerText = AddAccountAction.LABEL + '...';
}
return null;
return undefined;
}
private updateAccountList(accounts: azdata.Account[]): void {
// keep the selection to the current one
let selectedElements = this._accountList.getSelectedElements();
const selectedElements = this._accountList.getSelectedElements();
// find selected index
let selectedIndex: number;
@@ -227,8 +226,8 @@ export class AccountPicker extends Disposable {
* Update theming that is specific to account picker
*/
private updateTheme(theme: ITheme): void {
let linkColor = theme.getColor(buttonBackground);
let link = linkColor ? linkColor.toString() : null;
const linkColor = theme.getColor(buttonBackground);
const link = linkColor ? linkColor.toString() : null;
this._refreshContainer.style.color = link;
if (this._refreshContainer) {
this._refreshContainer.style.color = link;

View File

@@ -3,13 +3,12 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Event, Emitter } from 'vs/base/common/event';
import * as azdata from 'azdata';
import { IAccountPickerService } from 'sql/platform/accountManagement/common/accountPicker';
import { AccountPicker } from 'sql/platform/accountManagement/browser/accountPicker';
import { IAccountPickerService } from 'sql/platform/accounts/common/accountPicker';
import { AccountPicker } from 'sql/platform/accounts/browser/accountPicker';
export class AccountPickerService implements IAccountPickerService {
_serviceBrand: any;

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/autoOAuthDialog';
import { Builder, $ } from 'sql/base/browser/builder';
import { IThemeService } from 'vs/platform/theme/common/themeService';

View File

@@ -3,13 +3,12 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import Severity from 'vs/base/common/severity';
import { localize } from 'vs/nls';
import { AutoOAuthDialog } from 'sql/parts/accountManagement/autoOAuthDialog/autoOAuthDialog';
import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import { AutoOAuthDialog } from 'sql/platform/accounts/browser/autoOAuthDialog';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
export class AutoOAuthDialogController {
@@ -33,7 +32,7 @@ export class AutoOAuthDialogController {
public openAutoOAuthDialog(providerId: string, title: string, message: string, userCode: string, uri: string): Thenable<void> {
if (this._providerId !== null) {
// If a oauth flyout is already open, return an error
let errorMessage = localize('oauthFlyoutIsAlreadyOpen', 'Cannot start auto OAuth. An auto OAuth is already in progress.');
const errorMessage = localize('oauthFlyoutIsAlreadyOpen', 'Cannot start auto OAuth. An auto OAuth is already in progress.');
this._errorMessageService.showDialog(Severity.Error, '', errorMessage);
return Promise.reject(new Error('Auto OAuth dialog already open'));
}

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/firewallRuleDialog';
import { Builder, $ } from 'sql/base/browser/builder';
import * as DOM from 'vs/base/browser/dom';
@@ -24,10 +22,10 @@ import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import * as azdata from 'azdata';
import { Button } from 'sql/base/browser/ui/button/button';
import { Modal } from 'sql/workbench/browser/modal/modal';
import { FirewallRuleViewModel } from 'sql/parts/accountManagement/firewallRuleDialog/firewallRuleViewModel';
import { FirewallRuleViewModel } from 'sql/platform/accounts/common/firewallRuleViewModel';
import { attachModalDialogStyler, attachButtonStyler } from 'sql/platform/theme/common/styler';
import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
import { IAccountPickerService } from 'sql/platform/accountManagement/common/accountPicker';
import { IAccountPickerService } from 'sql/platform/accounts/common/accountPicker';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
@@ -173,7 +171,7 @@ export class FirewallRuleDialog extends Modal {
let firewallRuleSection;
$().div({ 'class': 'firewall-rule-section new-section' }, (firewallRuleContainer) => {
firewallRuleSection = firewallRuleContainer.getHTMLElement();
let firewallRuleLabel = localize('filewallRule', 'Firewall rule');
const firewallRuleLabel = localize('filewallRule', 'Firewall rule');
this.createLabelElement(firewallRuleContainer, firewallRuleLabel, true);
firewallRuleContainer.div({ 'class': 'radio-section' }, (radioContainer) => {
const form = DOM.append(radioContainer.getHTMLElement(), DOM.$('form.firewall-rule'));
@@ -244,8 +242,8 @@ export class FirewallRuleDialog extends Modal {
// Update theming that is specific to firewall rule flyout body
private updateTheme(theme: ITheme): void {
let linkColor = theme.getColor(buttonBackground);
let link = linkColor ? linkColor.toString() : null;
const linkColor = theme.getColor(buttonBackground);
const link = linkColor ? linkColor.toString() : null;
if (this._helpLink) {
this._helpLink.style.color = link;
}

View File

@@ -3,15 +3,14 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import Severity from 'vs/base/common/severity';
import { localize } from 'vs/nls';
import * as azdata from 'azdata';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { FirewallRuleDialog } from 'sql/parts/accountManagement/firewallRuleDialog/firewallRuleDialog';
import { IAccountManagementService, AzureResource } from 'sql/platform/accountManagement/common/interfaces';
import { FirewallRuleDialog } from 'sql/platform/accounts/browser/firewallRuleDialog';
import { IAccountManagementService, AzureResource } from 'sql/platform/accounts/common/interfaces';
import { IResourceProviderService } from 'sql/workbench/services/resourceProvider/common/resourceProviderService';
import { Deferred } from 'sql/base/common/promise';
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
@@ -59,7 +58,7 @@ export class FirewallRuleDialogController {
}
private handleOnCreateFirewallRule(): void {
let resourceProviderId = this._resourceProviderId;
const resourceProviderId = this._resourceProviderId;
this._accountManagementService.getSecurityToken(this._firewallRuleDialog.viewModel.selectedAccount, AzureResource.ResourceManagement).then(tokenMappings => {
let firewallRuleInfo: azdata.FirewallRuleInfo = {

View File

@@ -2,6 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.no-account-view {
font-size: 12px;
padding: 15px;
@@ -102,7 +103,3 @@
.account-view .monaco-list .monaco-list-row.focused .list-row .actions-container{
display: block;
}
.account-view .monaco-list .monaco-list-row {
}

View File

Before

Width:  |  Height:  |  Size: 850 B

After

Width:  |  Height:  |  Size: 850 B

View File

Before

Width:  |  Height:  |  Size: 918 B

After

Width:  |  Height:  |  Size: 918 B

View File

Before

Width:  |  Height:  |  Size: 894 B

After

Width:  |  Height:  |  Size: 894 B

View File

@@ -3,15 +3,13 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import { Event, Emitter } from 'vs/base/common/event';
import { localize } from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { error } from 'sql/base/common/log';
import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
import { IDialogService, IConfirmation } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
import Severity from 'vs/base/common/severity';
@@ -47,26 +45,19 @@ export class AddAccountAction extends Action {
}
public run(): Promise<boolean> {
let self = this;
// Fire the event that we've started adding accounts
this._addAccountStartEmitter.fire();
return new Promise((resolve, reject) => {
self._accountManagementService.addAccount(self._providerId)
.then(
() => {
self._addAccountCompleteEmitter.fire();
resolve(true);
},
err => {
error(`Error while adding account: ${err}`);
self._addAccountErrorEmitter.fire(err);
self._addAccountCompleteEmitter.fire();
reject(err);
}
);
});
return Promise.resolve(this._accountManagementService.addAccount(this._providerId)
.then(() => {
this._addAccountCompleteEmitter.fire();
return true;
}, err => {
error(`Error while adding account: ${err}`);
this._addAccountErrorEmitter.fire(err);
this._addAccountCompleteEmitter.fire();
}));
}
}
@@ -87,10 +78,8 @@ export class RemoveAccountAction extends Action {
}
public run(): Promise<boolean> {
let self = this;
// Ask for Confirm
let confirm: IConfirmation = {
const confirm: IConfirmation = {
message: localize('confirmRemoveUserAccountMessage', "Are you sure you want to remove '{0}'?", this._account.displayInfo.displayName),
primaryButton: localize('accountActions.yes', 'Yes'),
secondaryButton: localize('accountActions.no', 'No'),
@@ -101,19 +90,13 @@ export class RemoveAccountAction extends Action {
if (!result) {
return Promise.resolve(false);
} else {
return new Promise((resolve, reject) => {
self._accountManagementService.removeAccount(self._account.key)
.then(
(result) => { resolve(result); },
(err) => {
// Must handle here as this is an independent action
self._notificationService.notify({
severity: Severity.Error,
message: localize('removeAccountFailed', 'Failed to remove account')
});
resolve(false);
}
);
return Promise.resolve(this._accountManagementService.removeAccount(this._account.key)).catch(err => {
// Must handle here as this is an independent action
this._notificationService.notify({
severity: Severity.Error,
message: localize('removeAccountFailed', 'Failed to remove account')
});
return false;
});
}
});
@@ -154,23 +137,17 @@ export class RefreshAccountAction extends Action {
super(RefreshAccountAction.ID, RefreshAccountAction.LABEL, 'refresh-account-action icon refresh');
}
public run(): Promise<boolean> {
let self = this;
return new Promise((resolve, reject) => {
if (self.account) {
self._accountManagementService.refreshAccount(self.account)
.then(
() => {
resolve(true);
},
if (this.account) {
return Promise.resolve(this._accountManagementService.refreshAccount(this.account)
.then(() => true,
err => {
error(`Error while refreshing account: ${err}`);
reject(err);
return Promise.reject(err);
}
);
} else {
let errorMessage = localize('NoAccountToRefresh', 'There is no account to refresh');
reject(errorMessage);
}
});
));
} else {
const errorMessage = localize('NoAccountToRefresh', 'There is no account to refresh');
return Promise.reject(errorMessage);
}
}
}

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Event } from 'vs/base/common/event';

View File

@@ -3,12 +3,11 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import { Event, Emitter } from 'vs/base/common/event';
import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import { UpdateAccountListEventParams } from 'sql/platform/accountManagement/common/eventTypes';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
import { UpdateAccountListEventParams } from 'sql/platform/accounts/common/eventTypes';
/**
* View model for account picker
@@ -24,13 +23,11 @@ export class AccountPickerViewModel {
private _providerId: string,
@IAccountManagementService private _accountManagementService: IAccountManagementService
) {
let self = this;
// Create our event emitters
this._updateAccountListEmitter = new Emitter<UpdateAccountListEventParams>();
// Register handlers for any changes to the accounts
this._accountManagementService.updateAccountListEvent(arg => self._updateAccountListEmitter.fire(arg));
this._accountManagementService.updateAccountListEvent(arg => this._updateAccountListEmitter.fire(arg));
}
// PUBLIC METHODS //////////////////////////////////////////////////////
@@ -41,10 +38,10 @@ export class AccountPickerViewModel {
public initialize(): Thenable<azdata.Account[]> {
// Load a baseline of the accounts for the provider
return this._accountManagementService.getAccountsForProvider(this._providerId)
.then(null, () => {
.then(undefined, () => {
// In the event we failed to lookup accounts for the provider, just send
// back an empty collection
return [];
});
}
}
}

View File

@@ -3,11 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import { AccountAdditionResult } from 'sql/platform/accountManagement/common/eventTypes';
import { IAccountStore } from 'sql/platform/accountManagement/common/interfaces';
import { AccountAdditionResult } from 'sql/platform/accounts/common/eventTypes';
import { IAccountStore } from 'sql/platform/accounts/common/interfaces';
import { deepClone } from 'vs/base/common/objects';
export default class AccountStore implements IAccountStore {
// CONSTANTS ///////////////////////////////////////////////////////////
@@ -20,57 +19,47 @@ export default class AccountStore implements IAccountStore {
// PUBLIC METHODS //////////////////////////////////////////////////////
public addOrUpdate(newAccount: azdata.Account): Thenable<AccountAdditionResult> {
let self = this;
return this.doOperation(() => {
return self.readFromMemento()
return this.readFromMemento()
.then(accounts => {
// Determine if account exists and proceed accordingly
let match = accounts.findIndex(account => AccountStore.findAccountByKey(account.key, newAccount.key));
const match = accounts.findIndex(account => AccountStore.findAccountByKey(account.key, newAccount.key));
return match < 0
? self.addToAccountList(accounts, newAccount)
: self.updateAccountList(accounts, newAccount.key, (matchAccount) => { AccountStore.mergeAccounts(newAccount, matchAccount); });
? this.addToAccountList(accounts, newAccount)
: this.updateAccountList(accounts, newAccount.key, matchAccount => AccountStore.mergeAccounts(newAccount, matchAccount));
})
.then(result => self.writeToMemento(result.updatedAccounts).then(() => result))
.then(result => this.writeToMemento(result.updatedAccounts).then(() => result))
.then(result => <AccountAdditionResult>result);
});
}
public getAccountsByProvider(providerId: string): Thenable<azdata.Account[]> {
let self = this;
return this.doOperation(() => {
return self.readFromMemento()
return this.readFromMemento()
.then(accounts => accounts.filter(account => account.key.providerId === providerId));
});
}
public getAllAccounts(): Thenable<azdata.Account[]> {
let self = this;
return this.doOperation(() => {
return self.readFromMemento();
return this.readFromMemento();
});
}
public remove(key: azdata.AccountKey): Thenable<boolean> {
let self = this;
return this.doOperation(() => {
return self.readFromMemento()
.then(accounts => self.removeFromAccountList(accounts, key))
.then(result => self.writeToMemento(result.updatedAccounts).then(() => result))
return this.readFromMemento()
.then(accounts => this.removeFromAccountList(accounts, key))
.then(result => this.writeToMemento(result.updatedAccounts).then(() => result))
.then(result => result.accountRemoved);
});
}
public update(key: azdata.AccountKey, updateOperation: (account: azdata.Account) => void): Thenable<boolean> {
let self = this;
return this.doOperation(() => {
return self.readFromMemento()
.then(accounts => self.updateAccountList(accounts, key, updateOperation))
.then(result => self.writeToMemento(result.updatedAccounts).then(() => result))
return this.readFromMemento()
.then(accounts => this.updateAccountList(accounts, key, updateOperation))
.then(result => this.writeToMemento(result.updatedAccounts).then(() => result))
.then(result => result.accountModified);
});
}
@@ -111,7 +100,7 @@ export default class AccountStore implements IAccountStore {
private addToAccountList(accounts: azdata.Account[], accountToAdd: azdata.Account): AccountListOperationResult {
// Check if the entry already exists
let match = accounts.findIndex(account => AccountStore.findAccountByKey(account.key, accountToAdd.key));
const match = accounts.findIndex(account => AccountStore.findAccountByKey(account.key, accountToAdd.key));
if (match >= 0) {
// Account already exists, we won't do anything
return {
@@ -136,7 +125,7 @@ export default class AccountStore implements IAccountStore {
private removeFromAccountList(accounts: azdata.Account[], accountToRemove: azdata.AccountKey): AccountListOperationResult {
// Check if the entry exists
let match = accounts.findIndex(account => AccountStore.findAccountByKey(account.key, accountToRemove));
const match = accounts.findIndex(account => AccountStore.findAccountByKey(account.key, accountToRemove));
if (match >= 0) {
// Account exists, remove it from the account list
accounts.splice(match, 1);
@@ -153,7 +142,7 @@ export default class AccountStore implements IAccountStore {
private updateAccountList(accounts: azdata.Account[], accountToUpdate: azdata.AccountKey, updateOperation: (account: azdata.Account) => void): AccountListOperationResult {
// Check if the entry exists
let match = accounts.findIndex(account => AccountStore.findAccountByKey(account.key, accountToUpdate));
const match = accounts.findIndex(account => AccountStore.findAccountByKey(account.key, accountToUpdate));
if (match < 0) {
// Account doesn't exist, we won't do anything
return {
@@ -186,14 +175,14 @@ export default class AccountStore implements IAccountStore {
}
// Make a deep copy of the account list to ensure that the memento list isn't obliterated
accounts = JSON.parse(JSON.stringify(accounts));
accounts = deepClone(accounts);
return Promise.resolve(accounts);
}
private writeToMemento(accounts: azdata.Account[]): Thenable<void> {
// Store a shallow copy of the account list to disconnect the memento list from the active list
this._memento[AccountStore.MEMENTO_KEY] = JSON.parse(JSON.stringify(accounts));
this._memento[AccountStore.MEMENTO_KEY] = deepClone(accounts);
return Promise.resolve();
}
}

View File

@@ -3,12 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import { Event, Emitter } from 'vs/base/common/event';
import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accountManagement/common/eventTypes';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accounts/common/eventTypes';
/**
* View model for account dialog
@@ -24,18 +22,16 @@ export class AccountViewModel {
private _updateAccountListEmitter: Emitter<UpdateAccountListEventParams>;
public get updateAccountListEvent(): Event<UpdateAccountListEventParams> { return this._updateAccountListEmitter.event; }
constructor( @IAccountManagementService private _accountManagementService: IAccountManagementService) {
let self = this;
constructor(@IAccountManagementService private _accountManagementService: IAccountManagementService) {
// Create our event emitters
this._addProviderEmitter = new Emitter<AccountProviderAddedEventParams>();
this._removeProviderEmitter = new Emitter<azdata.AccountProviderMetadata>();
this._updateAccountListEmitter = new Emitter<UpdateAccountListEventParams>();
// Register handlers for any changes to the providers or accounts
this._accountManagementService.addAccountProviderEvent(arg => self._addProviderEmitter.fire(arg));
this._accountManagementService.removeAccountProviderEvent(arg => self._removeProviderEmitter.fire(arg));
this._accountManagementService.updateAccountListEvent(arg => self._updateAccountListEmitter.fire(arg));
this._accountManagementService.addAccountProviderEvent(arg => this._addProviderEmitter.fire(arg));
this._accountManagementService.removeAccountProviderEvent(arg => this._removeProviderEmitter.fire(arg));
this._accountManagementService.updateAccountListEvent(arg => this._updateAccountListEmitter.fire(arg));
}
// PUBLIC METHODS //////////////////////////////////////////////////////
@@ -45,30 +41,26 @@ export class AccountViewModel {
*
*/
public initialize(): Thenable<AccountProviderAddedEventParams[]> {
let self = this;
// Load a baseline of the account provider metadata and accounts
// 1) Get all the providers from the account management service
// 2) For each provider, get the accounts
// 3) Build parameters to add a provider and return it
return this._accountManagementService.getAccountProviderMetadata()
.then(
(providers: azdata.AccountProviderMetadata[]) => {
let promises = providers.map(provider => {
return self._accountManagementService.getAccountsForProvider(provider.id)
.then(
accounts => <AccountProviderAddedEventParams>{
addedProvider: provider,
initialAccounts: accounts
},
() => { /* Swallow failures at getting accounts, we'll just hide that provider */ });
(providers: azdata.AccountProviderMetadata[]) => {
const promises = providers.map(provider => {
return this._accountManagementService.getAccountsForProvider(provider.id)
.then(
accounts => <AccountProviderAddedEventParams>{
addedProvider: provider,
initialAccounts: accounts
},
() => { /* Swallow failures at getting accounts, we'll just hide that provider */ });
});
return Promise.all(promises);
}, () => {
/* Swallow failures and just pretend we don't have any providers */
return [];
});
return Promise.all(promises);
},
() => {
/* Swallow failures and just pretend we don't have any providers */
return [];
}
);
}
}
}

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
/**

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
/**
@@ -64,4 +63,4 @@ export class FirewallRuleViewModel {
this._defaultFromSubnetIPRange = ipAddress.replace(/\.[0-9]+$/g, '.0');
this._defaultToSubnetIPRange = ipAddress.replace(/\.[0-9]+$/g, '.255');
}
}
}

View File

@@ -3,11 +3,9 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import { Event } from 'vs/base/common/event';
import { AccountAdditionResult, AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accountManagement/common/eventTypes';
import { AccountAdditionResult, AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accounts/common/eventTypes';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const SERVICE_ID = 'accountManagementService';

View File

@@ -33,7 +33,7 @@ import { Deferred } from 'sql/base/common/promise';
import { ConnectionOptionSpecialType } from 'sql/workbench/api/common/sqlExtHostTypes';
import { values, entries } from 'sql/base/common/objects';
import { ConnectionProviderProperties, IConnectionProviderRegistry, Extensions as ConnectionProviderExtensions } from 'sql/workbench/parts/connection/common/connectionProviderExtension';
import { IAccountManagementService, AzureResource } from 'sql/platform/accountManagement/common/interfaces';
import { IAccountManagementService, AzureResource } from 'sql/platform/accounts/common/interfaces';
import { IServerGroupController, IServerGroupDialogCallbacks } from 'sql/platform/serverGroup/common/serverGroupController';
import * as azdata from 'azdata';

View File

@@ -5,7 +5,7 @@
'use strict';
import * as azdata from 'azdata';
import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import {
ExtHostAccountManagementShape,
@@ -15,7 +15,7 @@ import {
} from 'sql/workbench/api/node/sqlExtHost.protocol';
import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { UpdateAccountListEventParams } from 'sql/platform/accountManagement/common/eventTypes';
import { UpdateAccountListEventParams } from 'sql/platform/accounts/common/eventTypes';
@extHostNamedCustomer(SqlMainContext.MainThreadAccountManagement)
export class MainThreadAccountManagement implements MainThreadAccountManagementShape {

View File

@@ -16,12 +16,12 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { Memento } from 'vs/workbench/common/memento';
import AccountStore from 'sql/platform/accountManagement/common/accountStore';
import { AccountDialogController } from 'sql/parts/accountManagement/accountDialog/accountDialogController';
import { AutoOAuthDialogController } from 'sql/parts/accountManagement/autoOAuthDialog/autoOAuthDialogController';
import { AccountListStatusbarItem } from 'sql/parts/accountManagement/accountListStatusbar/accountListStatusbarItem';
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accountManagement/common/eventTypes';
import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import AccountStore from 'sql/platform/accounts/common/accountStore';
import { AccountDialogController } from 'sql/platform/accounts/browser/accountDialogController';
import { AutoOAuthDialogController } from 'sql/platform/accounts/browser/autoOAuthDialogController';
import { AccountListStatusbarItem } from 'sql/platform/accounts/browser/accountListStatusbarItem';
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accounts/common/eventTypes';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
import { Deferred } from 'sql/base/common/promise';
export class AccountManagementService implements IAccountManagementService {
@@ -117,7 +117,7 @@ export class AccountManagementService implements IAccountManagementService {
reason => {
console.warn(`Account update handler encountered error: ${reason}`);
}
);
);
}
@@ -308,8 +308,8 @@ export class AccountManagementService implements IAccountManagementService {
public cancelAutoOAuthDeviceCode(providerId: string): void {
this.doWithProvider(providerId, provider => provider.provider.autoOAuthCancelled())
.then( // Swallow errors
null,
err => { console.warn(`Error when cancelling auto OAuth: ${err}`); }
null,
err => { console.warn(`Error when cancelling auto OAuth: ${err}`); }
)
.then(() => this.autoOAuthDialogController.closeAutoOAuthDialog());
}

View File

@@ -22,7 +22,7 @@ import { IConnectionManagementService } from 'sql/platform/connection/common/con
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import * as styler from 'sql/platform/theme/common/styler';
import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
import * as azdata from 'azdata';

View File

@@ -12,7 +12,7 @@ import { IResourceProviderService, IHandleFirewallRuleResult } from 'sql/workben
import * as Constants from 'sql/common/constants';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import * as TelemetryUtils from 'sql/common/telemetryUtilities';
import { FirewallRuleDialogController } from 'sql/parts/accountManagement/firewallRuleDialog/firewallRuleDialogController';
import { FirewallRuleDialogController } from 'sql/platform/accounts/browser/firewallRuleDialogController';
import * as azdata from 'azdata';
@@ -77,8 +77,8 @@ export class ResourceProviderService implements IResourceProviderService {
handleFirewallRuleResult = { canHandleFirewallRule: response.result, ipAddress: response.ipAddress, resourceProviderId: key };
}
},
() => { /* Swallow failures at getting accounts, we'll just hide that provider */
}));
() => { /* Swallow failures at getting accounts, we'll just hide that provider */
}));
}
}