Move code around for more linting (#8190)

* testing

* moving around all the code

* fix strict nulls
This commit is contained in:
Anthony Dresser
2019-11-04 10:41:28 -08:00
committed by GitHub
parent 3c702c15e2
commit ade68b184d
145 changed files with 248 additions and 231 deletions

View File

@@ -9,8 +9,8 @@ import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { MainThreadModelViewDialogShape, SqlMainContext, ExtHostModelViewDialogShape, SqlExtHostContext } from 'sql/workbench/api/common/sqlExtHost.protocol';
import { Dialog, DialogTab, DialogButton, WizardPage, Wizard } from 'sql/platform/dialog/common/dialogTypes';
import { CustomDialogService } from 'sql/platform/dialog/browser/customDialogService';
import { Dialog, DialogTab, DialogButton, WizardPage, Wizard } from 'sql/workbench/services/dialog/common/dialogTypes';
import { CustomDialogService } from 'sql/workbench/services/dialog/browser/customDialogService';
import { IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails, IModelViewWizardPageDetails, IModelViewWizardDetails } from 'sql/workbench/api/common/sqlExtHostTypes';
import { ModelViewInput, ModelViewInputModel, ModeViewSaveHandler } from 'sql/workbench/browser/modelComponents/modelViewInput';

View File

@@ -5,7 +5,7 @@
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { IAngularEventingService, AngularEventType } from 'sql/platform/angularEventing/common/angularEventingService';
import { IAngularEventingService, AngularEventType } from 'sql/platform/angularEventing/browser/angularEventingService';
import { IInsightsDialogService } from 'sql/workbench/services/insights/browser/insightsDialogService';
import { Task } from 'sql/platform/tasks/browser/tasksRegistry';

View File

@@ -13,7 +13,7 @@ import * as azdata from 'azdata';
import { ComponentBase } from 'sql/workbench/browser/modelComponents/componentBase';
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/workbench/browser/modelComponents/interfaces';
import { Checkbox, ICheckboxOptions } from 'sql/base/browser/ui/checkbox/checkbox';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { attachCheckboxStyler } from 'sql/platform/theme/common/styler';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';

View File

@@ -13,7 +13,7 @@ import { IComponent, IComponentDescriptor, IModelStore } from 'sql/workbench/bro
import { FormLayout, FormItemLayout } from 'azdata';
import { ContainerBase } from 'sql/workbench/browser/modelComponents/componentBase';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
export interface TitledFormItemLayout {
title: string;

View File

@@ -19,10 +19,10 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { memoize } from 'vs/base/common/decorators';
import { generateUuid } from 'vs/base/common/uuid';
import { Event } from 'vs/base/common/event';
import { LayoutRequestParams } from 'sql/platform/dialog/browser/dialogContainer.component';
import { LayoutRequestParams } from 'sql/workbench/services/dialog/browser/dialogContainer.component';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { ILogService } from 'vs/platform/log/common/log';
import { IBootstrapParams } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
const componentRegistry = <IComponentRegistry>Registry.as(Extensions.ComponentContribution);

View File

@@ -10,7 +10,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
import { memoize } from 'vs/base/common/decorators';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { IModelView } from 'sql/platform/model/browser/modelViewService';
import { ViewBase } from 'sql/workbench/browser/modelComponents/viewBase';
import { IModelViewService } from 'sql/platform/modelComponents/browser/modelViewService';

View File

@@ -10,7 +10,7 @@ import { EditorInput, EditorModel, ConfirmResult } from 'vs/workbench/common/edi
import * as DOM from 'vs/base/browser/dom';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { DialogPane } from 'sql/platform/dialog/browser/dialogPane';
import { DialogPane } from 'sql/workbench/services/dialog/browser/dialogPane';
import { Emitter, Event } from 'vs/base/common/event';
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { IThemeService } from 'vs/platform/theme/common/themeService';

View File

@@ -14,7 +14,7 @@ import { Orientation, ToolbarLayout } from 'sql/workbench/api/common/sqlExtHostT
import { IComponent, IComponentDescriptor, IModelStore } from 'sql/workbench/browser/modelComponents/interfaces';
import { ContainerBase } from 'sql/workbench/browser/modelComponents/componentBase';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
export interface ToolbarItemConfig {
title?: string;

View File

@@ -14,7 +14,7 @@ import * as azdata from 'azdata';
import { ComponentBase } from 'sql/workbench/browser/modelComponents/componentBase';
import { IComponent, IComponentDescriptor, IModelStore } from 'sql/workbench/browser/modelComponents/interfaces';
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { TreeComponentRenderer } from 'sql/workbench/browser/modelComponents/treeComponentRenderer';
import { TreeComponentDataSource } from 'sql/workbench/browser/modelComponents/treeDataSource';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';

View File

@@ -0,0 +1,357 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/accountDialog';
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';
import { localize } from 'vs/nls';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachListStyler } from 'vs/platform/theme/common/styler';
import { IAction } from 'vs/base/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { SplitView, Sizing } from 'vs/base/browser/ui/splitview/splitview';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ViewletPanel, IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { values } from 'vs/base/common/map';
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/platform/accounts/common/accountViewModel';
import { AddAccountAction } from 'sql/platform/accounts/common/accountActions';
import { AccountListRenderer, AccountListDelegate } from 'sql/workbench/parts/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/platform/telemetry/common/telemetryKeys';
import { ILogService } from 'vs/platform/log/common/log';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
class AccountPanel extends ViewletPanel {
public index: number;
private accountList: List<azdata.Account>;
constructor(
private options: IViewletPanelOptions,
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService,
@IInstantiationService private instantiationService: IInstantiationService,
@IThemeService private themeService: IThemeService,
@IContextKeyService contextKeyService: IContextKeyService
) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService);
}
protected renderBody(container: HTMLElement): void {
this.accountList = new List<azdata.Account>('AccountList', container, new AccountListDelegate(AccountDialog.ACCOUNTLIST_HEIGHT), [this.instantiationService.createInstance(AccountListRenderer)]);
this._register(attachListStyler(this.accountList, this.themeService));
}
protected layoutBody(size: number): void {
if (this.accountList) {
this.accountList.layout(size);
}
}
public get length(): number {
return this.accountList.length;
}
public focus() {
this.accountList.domFocus();
}
public updateAccounts(accounts: azdata.Account[]) {
this.accountList.splice(0, this.accountList.length, accounts);
}
public setSelection(indexes: number[]) {
this.accountList.setSelection(indexes);
}
public getActions(): IAction[] {
return [this.instantiationService.createInstance(
AddAccountAction,
this.options.id
)];
}
}
export interface IProviderViewUiComponent {
view: AccountPanel;
addAccountAction: AddAccountAction;
}
export class AccountDialog extends Modal {
public static ACCOUNTLIST_HEIGHT = 77;
public viewModel: AccountViewModel;
// MEMBER VARIABLES ////////////////////////////////////////////////////
private _providerViewsMap = new Map<string, IProviderViewUiComponent>();
private _closeButton: Button;
private _addAccountButton: Button;
private _splitView: SplitView;
private _container: HTMLElement;
private _splitViewContainer: HTMLElement;
private _noaccountViewContainer: HTMLElement;
// EVENTING ////////////////////////////////////////////////////////////
private _onAddAccountErrorEmitter: Emitter<string>;
public get onAddAccountErrorEvent(): Event<string> { return this._onAddAccountErrorEmitter.event; }
private _onCloseEmitter: Emitter<void>;
public get onCloseEvent(): Event<void> { return this._onCloseEmitter.event; }
constructor(
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IThemeService themeService: IThemeService,
@IInstantiationService private _instantiationService: IInstantiationService,
@IContextMenuService private _contextMenuService: IContextMenuService,
@IKeybindingService private _keybindingService: IKeybindingService,
@IConfigurationService private _configurationService: IConfigurationService,
@ITelemetryService telemetryService: ITelemetryService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IClipboardService clipboardService: IClipboardService,
@ILogService logService: ILogService,
@ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService
) {
super(
localize('linkedAccounts', "Linked accounts"),
TelemetryKeys.Accounts,
telemetryService,
layoutService,
clipboardService,
themeService,
logService,
textResourcePropertiesService,
contextKeyService,
{ hasSpinner: true }
);
// Setup the event emitters
this._onAddAccountErrorEmitter = new Emitter<string>();
this._onCloseEmitter = new Emitter<void>();
// Create the view model and wire up the events
this.viewModel = this._instantiationService.createInstance(AccountViewModel);
this.viewModel.addProviderEvent(arg => { this.addProvider(arg); });
this.viewModel.removeProviderEvent(arg => { this.removeProvider(arg); });
this.viewModel.updateAccountListEvent(arg => { this.updateProviderAccounts(arg); });
// Load the initial contents of the view model
this.viewModel.initialize()
.then(addedProviders => {
for (const addedProvider of addedProviders) {
this.addProvider(addedProvider);
}
});
}
// MODAL OVERRIDE METHODS //////////////////////////////////////////////
protected layout(height?: number): void {
this._splitView.layout(DOM.getContentHeight(this._container));
}
public render() {
super.render();
attachModalDialogStyler(this, this._themeService);
this._closeButton = this.addFooterButton(localize('accountDialog.close', "Close"), () => this.close());
this.registerListeners();
}
protected renderBody(container: HTMLElement) {
this._container = container;
this._splitViewContainer = DOM.$('div.account-view.monaco-panel-view');
DOM.append(container, this._splitViewContainer);
this._splitView = new SplitView(this._splitViewContainer);
this._noaccountViewContainer = DOM.$('div.no-account-view');
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
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(() => {
(<IProviderViewUiComponent>values(this._providerViewsMap)[0]).addAccountAction.run();
}));
DOM.append(container, this._noaccountViewContainer);
}
private registerListeners(): void {
// Theme styler
this._register(attachButtonStyler(this._closeButton, this._themeService));
this._register(attachButtonStyler(this._addAccountButton, this._themeService));
}
/* Overwrite escape key behavior */
protected onClose() {
this.close();
}
/* Overwrite enter key behavior */
protected onAccept() {
this.close();
}
public close() {
this._onCloseEmitter.fire();
this.hide();
}
public open() {
this.show();
if (!this.isEmptyLinkedAccount()) {
this.showSplitView();
} else {
this.showNoAccountContainer();
}
}
private showNoAccountContainer() {
this._splitViewContainer.hidden = true;
this._noaccountViewContainer.hidden = false;
this._addAccountButton.focus();
}
private showSplitView() {
this._splitViewContainer.hidden = false;
this._noaccountViewContainer.hidden = true;
if (values(this._providerViewsMap).length > 0) {
const firstView = values(this._providerViewsMap)[0];
if (firstView instanceof AccountPanel) {
firstView.setSelection([0]);
firstView.focus();
}
}
}
private isEmptyLinkedAccount(): boolean {
for (const provider of values(this._providerViewsMap)) {
const listView = provider.view;
if (listView && listView.length > 0) {
return false;
}
}
return true;
}
public dispose(): void {
super.dispose();
for (const provider of values(this._providerViewsMap)) {
if (provider.addAccountAction) {
provider.addAccountAction.dispose();
}
if (provider.view) {
provider.view.dispose();
}
}
}
// PRIVATE HELPERS /////////////////////////////////////////////////////
private addProvider(newProvider: AccountProviderAddedEventParams) {
// Skip adding the provider if it already exists
if (this._providerViewsMap.get(newProvider.addedProvider.id)) {
return;
}
// Account provider doesn't exist, so add it
// Create a scoped add account action
let addAccountAction = this._instantiationService.createInstance(
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(
{
id: newProvider.addedProvider.id,
title: newProvider.addedProvider.displayName,
ariaHeaderLabel: newProvider.addedProvider.displayName
},
this._keybindingService,
this._contextMenuService,
this._configurationService,
this._instantiationService,
this._themeService,
this.contextKeyService
);
attachPanelStyler(providerView, this._themeService);
const insertIndex = this._splitView.length;
// Append the list view to the split view
this._splitView.addView(providerView, Sizing.Distribute, insertIndex);
providerView.render();
providerView.index = insertIndex;
this._splitView.layout(DOM.getContentHeight(this._container));
// Set the initial items of the list
providerView.updateAccounts(newProvider.initialAccounts);
if (newProvider.initialAccounts.length > 0 && this._splitViewContainer.hidden) {
this.showSplitView();
}
this.layout();
// Store the view for the provider and action
this._providerViewsMap.set(newProvider.addedProvider.id, { view: providerView, addAccountAction: addAccountAction });
}
private removeProvider(removedProvider: azdata.AccountProviderMetadata) {
// Skip removing the provider if it doesn't exist
const providerView = this._providerViewsMap.get(removedProvider.id);
if (!providerView || !providerView.view) {
return;
}
// Remove the list view from the split view
this._splitView.removeView(providerView.view.index);
this._splitView.layout(DOM.getContentHeight(this._container));
// Remove the list view from our internal map
this._providerViewsMap.delete(removedProvider.id);
this.layout();
}
private updateProviderAccounts(args: UpdateAccountListEventParams) {
const providerMapping = this._providerViewsMap.get(args.providerId);
if (!providerMapping || !providerMapping.view) {
return;
}
providerMapping.view.updateAccounts(args.accountList);
if (args.accountList.length > 0 && this._splitViewContainer.hidden) {
this.showSplitView();
}
if (this.isEmptyLinkedAccount() && this._noaccountViewContainer.hidden) {
this.showNoAccountContainer();
}
this.layout();
}
}

View File

@@ -0,0 +1,47 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import Severity from 'vs/base/common/severity';
import { AccountDialog } from 'sql/workbench/parts/accounts/browser/accountDialog';
import { localize } from 'vs/nls';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
export class AccountDialogController {
// MEMBER VARIABLES ////////////////////////////////////////////////////
private _addAccountErrorTitle = localize('accountDialog.addAccountErrorTitle', "Error adding account");
private _accountDialog: AccountDialog;
public get accountDialog(): AccountDialog { return this._accountDialog; }
constructor(
@IInstantiationService private _instantiationService: IInstantiationService,
@IErrorMessageService private _errorMessageService: IErrorMessageService
) { }
/**
* Open account dialog
*/
public openAccountDialog(): void {
// Create a new dialog if one doesn't exist
if (!this._accountDialog) {
this._accountDialog = this._instantiationService.createInstance(AccountDialog);
this._accountDialog.onAddAccountErrorEvent(msg => this.handleOnAddAccountError(msg));
this._accountDialog.onCloseEvent(() => this.handleOnClose());
this._accountDialog.render();
}
// Open the dialog
this._accountDialog.open();
}
// PRIVATE HELPERS /////////////////////////////////////////////////////
private handleOnClose(): void { }
private handleOnAddAccountError(msg: string): void {
this._errorMessageService.showDialog(Severity.Error, this._addAccountErrorTitle, msg);
}
}

View File

@@ -0,0 +1,140 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
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/platform/accounts/common/accountActions';
import * as azdata from 'azdata';
export class AccountListDelegate implements IListVirtualDelegate<azdata.Account> {
constructor(
private _height: number
) {
}
public getHeight(element: azdata.Account): number {
return this._height;
}
public getTemplateId(element: azdata.Account): string {
return 'accountListRenderer';
}
}
export interface AccountPickerListTemplate {
root: HTMLElement;
icon: HTMLElement;
badgeContent: HTMLElement;
contextualDisplayName: HTMLElement;
label: HTMLElement;
displayName: HTMLElement;
}
export interface AccountListTemplate extends AccountPickerListTemplate {
content: HTMLElement;
actions: ActionBar;
}
export class AccountPickerListRenderer implements IListRenderer<azdata.Account, AccountPickerListTemplate> {
public static TEMPLATE_ID = 'accountListRenderer';
public get templateId(): string {
return AccountPickerListRenderer.TEMPLATE_ID;
}
public renderTemplate(container: HTMLElement): AccountPickerListTemplate {
const tableTemplate: AccountPickerListTemplate = Object.create(null);
const badge = DOM.$('div.badge');
tableTemplate.root = DOM.append(container, DOM.$('div.list-row.account-picker-list'));
tableTemplate.icon = DOM.append(tableTemplate.root, DOM.$('div.codicon'));
DOM.append(tableTemplate.icon, badge);
tableTemplate.badgeContent = DOM.append(badge, DOM.$('div.badge-content'));
tableTemplate.label = DOM.append(tableTemplate.root, DOM.$('div.label'));
tableTemplate.contextualDisplayName = DOM.append(tableTemplate.label, DOM.$('div.contextual-display-name'));
tableTemplate.displayName = DOM.append(tableTemplate.label, DOM.$('div.display-name'));
return tableTemplate;
}
public renderElement(account: azdata.Account, index: number, templateData: AccountPickerListTemplate): void {
// Set the account icon
templateData.icon.classList.add('account-logo', account.displayInfo.accountType);
templateData.contextualDisplayName.innerText = account.displayInfo.contextualDisplayName;
// show the account display name text, something like "User Name (user@email.com)"
if (account.displayInfo.userId && account.displayInfo.displayName) {
templateData.displayName.innerText = account.displayInfo.displayName + ' (' + account.displayInfo.userId + ')';
} else {
templateData.displayName.innerText = account.displayInfo.displayName;
}
if (account.isStale) {
templateData.badgeContent.className = 'badge-content codicon warning-badge';
} else {
templateData.badgeContent.className = 'badge-content';
}
}
public disposeTemplate(template: AccountPickerListTemplate): void {
// noop
}
public disposeElement(element: azdata.Account, index: number, templateData: AccountPickerListTemplate): void {
// noop
}
}
export class AccountListRenderer extends AccountPickerListRenderer {
constructor(
@IInstantiationService private _instantiationService: IInstantiationService
) {
super();
}
public get templateId(): string {
return AccountListRenderer.TEMPLATE_ID;
}
public renderTemplate(container: HTMLElement): AccountListTemplate {
const tableTemplate = super.renderTemplate(container) as AccountListTemplate;
tableTemplate.content = DOM.append(tableTemplate.label, DOM.$('div.content'));
tableTemplate.actions = new ActionBar(tableTemplate.root, { animated: false });
return tableTemplate;
}
public renderElement(account: azdata.Account, index: number, templateData: AccountListTemplate): void {
super.renderElement(account, index, templateData);
if (account.isStale) {
templateData.content.innerText = localize('refreshCredentials', "You need to refresh the credentials for this account.");
} else {
templateData.content.innerText = '';
}
templateData.actions.clear();
const actionOptions: IActionOptions = { icon: true, label: false };
if (account.isStale) {
const refreshAction = this._instantiationService.createInstance(RefreshAccountAction);
refreshAction.account = account;
templateData.actions.push(refreshAction, actionOptions);
} else {
// Todo: Will show filter action when API/GUI for filtering is implemented (#3022, #3024)
// templateData.actions.push(new ApplyFilterAction(ApplyFilterAction.ID, ApplyFilterAction.LABEL), actionOptions);
}
const removeAction = this._instantiationService.createInstance(RemoveAccountAction, account);
templateData.actions.push(removeAction, actionOptions);
}
}

View File

@@ -0,0 +1,88 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IExtensionPointUser, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { localize } from 'vs/nls';
import { createCSSRule, asCSSUrl } from 'vs/base/browser/dom';
import * as resources from 'vs/base/common/resources';
export interface IAccountContrib {
id: string;
icon?: IUserFriendlyIcon;
}
export type IUserFriendlyIcon = string | { light: string; dark: string; };
const account: IJSONSchema = {
type: 'object',
properties: {
id: {
description: localize('carbon.extension.contributes.account.id', "Identifier of the account type"),
type: 'string'
},
icon: {
description: localize('carbon.extension.contributes.account.icon', "(Optional) Icon which is used to represent the accpunt in the UI. Either a file path or a themable configuration"),
anyOf: [{
type: 'string'
},
{
type: 'object',
properties: {
light: {
description: localize('carbon.extension.contributes.account.icon.light', "Icon path when a light theme is used"),
type: 'string'
},
dark: {
description: localize('carbon.extension.contributes.account.icon.dark', "Icon path when a dark theme is used"),
type: 'string'
}
}
}]
}
}
};
export const accountsContribution: IJSONSchema = {
description: localize('carbon.extension.contributes.account', "Contributes icons to account provider."),
oneOf: [
account,
{
type: 'array',
items: account
}
]
};
ExtensionsRegistry.registerExtensionPoint<IAccountContrib | IAccountContrib[]>({ extensionPoint: 'account-type', jsonSchema: accountsContribution }).setHandler(extensions => {
function handleCommand(account: IAccountContrib, extension: IExtensionPointUser<any>) {
const { icon, id } = account;
if (icon) {
const iconClass = id;
if (typeof icon === 'string') {
const path = resources.joinPath(extension.description.extensionLocation, icon);
createCSSRule(`.codicon.${iconClass}`, `background-image: ${asCSSUrl(path)}`);
} else {
const light = resources.joinPath(extension.description.extensionLocation, icon.light);
const dark = resources.joinPath(extension.description.extensionLocation, icon.dark);
createCSSRule(`.codicon.${iconClass}`, `background-image: ${asCSSUrl(light)}`);
createCSSRule(`.vs-dark .codicon.${iconClass}, .hc-black .codicon.${iconClass}`, `background-image: ${asCSSUrl(dark)}`);
}
}
}
for (let extension of extensions) {
const { value } = extension;
if (Array.isArray<IAccountContrib>(value)) {
for (let command of value) {
handleCommand(command, extension);
}
} else {
handleCommand(value, extension);
}
}
});

View File

@@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Event } from 'vs/base/common/event';
import * as azdata from 'azdata';
export const IAccountPickerService = createDecorator<IAccountPickerService>('AccountPickerService');
export interface IAccountPickerService {
_serviceBrand: undefined;
renderAccountPicker(container: HTMLElement): void;
addAccountCompleteEvent: Event<void>;
addAccountErrorEvent: Event<string>;
addAccountStartEvent: Event<void>;
onAccountSelectionChangeEvent: Event<azdata.Account | undefined>;
selectedAccount: azdata.Account | undefined;
}

View File

@@ -0,0 +1,236 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/accountPicker';
import * as DOM from 'vs/base/browser/dom';
import { Event, Emitter } from 'vs/base/common/event';
import { List } from 'vs/base/browser/ui/list/listWidget';
import { IDropdownOptions } from 'vs/base/browser/ui/dropdown/dropdown';
import { IListEvent } from 'vs/base/browser/ui/list/list';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { buttonBackground } from 'vs/platform/theme/common/colorRegistry';
import { attachListStyler } from 'vs/platform/theme/common/styler';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
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/platform/accounts/common/accountActions';
import { AccountPickerListRenderer, AccountListDelegate } from 'sql/workbench/parts/accounts/browser/accountListRenderer';
import { AccountPickerViewModel } from 'sql/platform/accounts/common/accountPickerViewModel';
export class AccountPicker extends Disposable {
public static ACCOUNTPICKERLIST_HEIGHT = 47;
public viewModel: AccountPickerViewModel;
private _accountList: List<azdata.Account>;
private _rootElement: HTMLElement;
private _refreshContainer: HTMLElement;
private _listContainer: HTMLElement;
private _dropdown: DropdownList;
private _refreshAccountAction: RefreshAccountAction;
// EVENTING ////////////////////////////////////////////////////////////
private _addAccountCompleteEmitter: Emitter<void>;
public get addAccountCompleteEvent(): Event<void> { return this._addAccountCompleteEmitter.event; }
private _addAccountErrorEmitter: Emitter<string>;
public get addAccountErrorEvent(): Event<string> { return this._addAccountErrorEmitter.event; }
private _addAccountStartEmitter: Emitter<void>;
public get addAccountStartEvent(): Event<void> { return this._addAccountStartEmitter.event; }
private _onAccountSelectionChangeEvent: Emitter<azdata.Account | undefined>;
public get onAccountSelectionChangeEvent(): Event<azdata.Account | undefined> { return this._onAccountSelectionChangeEvent.event; }
constructor(
private _providerId: string,
@IThemeService private _themeService: IThemeService,
@IInstantiationService private _instantiationService: IInstantiationService,
@IContextViewService private _contextViewService: IContextViewService
) {
super();
// Create event emitters
this._addAccountCompleteEmitter = new Emitter<void>();
this._addAccountErrorEmitter = new Emitter<string>();
this._addAccountStartEmitter = new Emitter<void>();
this._onAccountSelectionChangeEvent = new Emitter<azdata.Account>();
// Create the view model, wire up the events, and initialize with baseline data
this.viewModel = this._instantiationService.createInstance(AccountPickerViewModel, this._providerId);
this.viewModel.updateAccountListEvent(arg => {
if (arg.providerId === this._providerId) {
this.updateAccountList(arg.accountList);
}
});
}
// PUBLIC METHODS //////////////////////////////////////////////////////
/**
* Render account picker
*/
public render(container: HTMLElement): void {
DOM.append(container, this._rootElement);
}
// PUBLIC METHODS //////////////////////////////////////////////////////
/**
* Create account picker component
*/
public createAccountPickerComponent() {
// Create an account list
const delegate = new AccountListDelegate(AccountPicker.ACCOUNTPICKERLIST_HEIGHT);
const accountRenderer = new AccountPickerListRenderer();
this._listContainer = DOM.$('div.account-list-container');
this._accountList = new List<azdata.Account>('AccountPicker', this._listContainer, delegate, [accountRenderer]);
this._register(attachListStyler(this._accountList, this._themeService));
this._rootElement = DOM.$('div.account-picker-container');
// Create a dropdown for account picker
const option: IDropdownOptions = {
contextViewProvider: this._contextViewService,
labelRenderer: (container) => this.renderLabel(container)
};
// Create the add account action
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());
this._dropdown = this._register(new DropdownList(this._rootElement, option, this._listContainer, this._accountList, addAccountAction));
this._register(attachDropdownStyler(this._dropdown, this._themeService));
this._register(this._accountList.onSelectionChange((e: IListEvent<azdata.Account>) => {
if (e.elements.length === 1) {
this._dropdown.renderLabel();
this.onAccountSelectionChange(e.elements[0]);
}
}));
// Create refresh account action
this._refreshContainer = DOM.append(this._rootElement, DOM.$('div.refresh-container'));
DOM.append(this._refreshContainer, DOM.$('div.sql codicon warning'));
const actionBar = new ActionBar(this._refreshContainer, { animated: false });
this._refreshAccountAction = this._instantiationService.createInstance(RefreshAccountAction);
actionBar.push(this._refreshAccountAction, { icon: false, label: true });
if (this._accountList.length > 0) {
this._accountList.setSelection([0]);
this.onAccountSelectionChange(this._accountList.getSelectedElements()[0]);
} else {
DOM.hide(this._refreshContainer);
}
this._register(this._themeService.onThemeChange(e => this.updateTheme(e)));
this.updateTheme(this._themeService.getTheme());
// Load the initial contents of the view model
this.viewModel.initialize()
.then((accounts: azdata.Account[]) => {
this.updateAccountList(accounts);
});
}
public dispose() {
super.dispose();
if (this._accountList) {
this._accountList.dispose();
}
}
// PRIVATE HELPERS /////////////////////////////////////////////////////
private onAccountSelectionChange(account: azdata.Account | undefined) {
this.viewModel.selectedAccount = account;
if (account && account.isStale) {
this._refreshAccountAction.account = account;
DOM.show(this._refreshContainer);
} else {
DOM.hide(this._refreshContainer);
}
this._onAccountSelectionChangeEvent.fire(account);
}
private renderLabel(container: HTMLElement): IDisposable | null {
if (container.hasChildNodes()) {
for (let i = 0; i < container.childNodes.length; i++) {
container.removeChild(container.childNodes.item(i));
}
}
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'));
const icon = DOM.append(row, DOM.$('div.codicon'));
DOM.append(icon, badge);
const badgeContent = DOM.append(badge, DOM.$('div.badge-content'));
const label = DOM.append(row, DOM.$('div.label'));
// Set the account icon
icon.classList.add('icon', account.displayInfo.accountType);
// TODO: Pick between the light and dark logo
label.innerText = account.displayInfo.displayName + ' (' + account.displayInfo.contextualDisplayName + ')';
if (account.isStale) {
badgeContent.className = 'badge-content codicon warning-badge';
} else {
badgeContent.className = 'badge-content';
}
} else {
const row = DOM.append(container, DOM.$('div.no-account-container'));
row.innerText = AddAccountAction.LABEL + '...';
}
return null;
}
private updateAccountList(accounts: azdata.Account[]): void {
// keep the selection to the current one
const selectedElements = this._accountList.getSelectedElements();
// find selected index
let selectedIndex: number | undefined;
if (selectedElements.length > 0 && accounts.length > 0) {
selectedIndex = accounts.findIndex((account) => {
return (account.key.accountId === selectedElements[0].key.accountId);
});
}
// Replace the existing list with the new one
this._accountList.splice(0, this._accountList.length, accounts);
if (this._accountList.length > 0) {
if (selectedIndex && selectedIndex !== -1) {
this._accountList.setSelection([selectedIndex]);
} else {
this._accountList.setSelection([0]);
}
} else {
// if the account is empty, re-render dropdown label
this.onAccountSelectionChange(undefined);
this._dropdown.renderLabel();
}
this._accountList.layout(this._accountList.contentHeight);
}
/**
* Update theming that is specific to account picker
*/
private updateTheme(theme: ITheme): void {
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

@@ -0,0 +1,65 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
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/workbench/parts/accounts/browser/accountPicker';
import { AccountPicker } from 'sql/workbench/parts/accounts/browser/accountPickerImpl';
export class AccountPickerService implements IAccountPickerService {
_serviceBrand: undefined;
private _accountPicker: AccountPicker;
// EVENTING ////////////////////////////////////////////////////////////
private _addAccountCompleteEmitter: Emitter<void>;
public get addAccountCompleteEvent(): Event<void> { return this._addAccountCompleteEmitter.event; }
private _addAccountErrorEmitter: Emitter<string>;
public get addAccountErrorEvent(): Event<string> { return this._addAccountErrorEmitter.event; }
private _addAccountStartEmitter: Emitter<void>;
public get addAccountStartEvent(): Event<void> { return this._addAccountStartEmitter.event; }
private _onAccountSelectionChangeEvent: Emitter<azdata.Account | undefined>;
public get onAccountSelectionChangeEvent(): Event<azdata.Account | undefined> { return this._onAccountSelectionChangeEvent.event; }
constructor(
@IInstantiationService private _instantiationService: IInstantiationService
) {
// Create event emitters
this._addAccountCompleteEmitter = new Emitter<void>();
this._addAccountErrorEmitter = new Emitter<string>();
this._addAccountStartEmitter = new Emitter<void>();
this._onAccountSelectionChangeEvent = new Emitter<azdata.Account>();
}
/**
* Get selected account
*/
public get selectedAccount(): azdata.Account | undefined {
return this._accountPicker.viewModel.selectedAccount;
}
/**
* Render account picker
*/
public renderAccountPicker(container: HTMLElement): void {
if (!this._accountPicker) {
// TODO: expand support to multiple providers
const providerId: string = 'azurePublicCloud';
this._accountPicker = this._instantiationService.createInstance(AccountPicker, providerId);
this._accountPicker.createAccountPickerComponent();
}
this._accountPicker.addAccountCompleteEvent(() => this._addAccountCompleteEmitter.fire());
this._accountPicker.addAccountErrorEvent((msg) => this._addAccountErrorEmitter.fire(msg));
this._accountPicker.addAccountStartEvent(() => this._addAccountStartEmitter.fire());
this._accountPicker.onAccountSelectionChangeEvent((account) => this._onAccountSelectionChangeEvent.fire(account));
this._accountPicker.render(container);
}
}

View File

@@ -0,0 +1,157 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/autoOAuthDialog';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
import { Event, Emitter } from 'vs/base/common/event';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { localize } from 'vs/nls';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { $, append } from 'vs/base/browser/dom';
import { Button } from 'sql/base/browser/ui/button/button';
import { Modal } from 'sql/workbench/browser/modal/modal';
import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
import { attachModalDialogStyler, attachButtonStyler } from 'sql/platform/theme/common/styler';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { ILogService } from 'vs/platform/log/common/log';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
export class AutoOAuthDialog extends Modal {
private _copyAndOpenButton: Button;
private _closeButton: Button;
private _userCodeInputBox: InputBox;
private _websiteInputBox: InputBox;
private _descriptionElement: HTMLElement;
// EVENTING ////////////////////////////////////////////////////////////
private _onHandleAddAccount = new Emitter<void>();
public get onHandleAddAccount(): Event<void> { return this._onHandleAddAccount.event; }
private _onCancel = new Emitter<void>();
public get onCancel(): Event<void> { return this._onCancel.event; }
private _onCloseEvent = new Emitter<void>();
public get onCloseEvent(): Event<void> { return this._onCloseEvent.event; }
constructor(
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IThemeService themeService: IThemeService,
@IContextViewService private _contextViewService: IContextViewService,
@ITelemetryService telemetryService: ITelemetryService,
@IContextKeyService contextKeyService: IContextKeyService,
@IClipboardService clipboardService: IClipboardService,
@ILogService logService: ILogService,
@ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService
) {
super(
'',
TelemetryKeys.AutoOAuth,
telemetryService,
layoutService,
clipboardService,
themeService,
logService,
textResourcePropertiesService,
contextKeyService,
{
isFlyout: true,
hasBackButton: true,
hasSpinner: true
}
);
}
public render() {
super.render();
attachModalDialogStyler(this, this._themeService);
this.backButton.onDidClick(() => this.cancel());
this._register(attachButtonStyler(this.backButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND }));
this._copyAndOpenButton = this.addFooterButton(localize('copyAndOpen', "Copy & Open"), () => this.addAccount());
this._closeButton = this.addFooterButton(localize('oauthDialog.cancel', "Cancel"), () => this.cancel());
this.registerListeners();
this._userCodeInputBox.disable();
this._websiteInputBox.disable();
}
protected layout(height?: number): void {
// NO OP
}
protected renderBody(container: HTMLElement) {
const body = append(container, $('.auto-oauth-dialog'));
this._descriptionElement = append(body, $('.auto-oauth-description-section.new-section'));
const addAccountSection = append(body, $('.auto-oauth-info-section.new-section'));
this._userCodeInputBox = this.createInputBoxHelper(addAccountSection, localize('userCode', "User code"));
this._websiteInputBox = this.createInputBoxHelper(addAccountSection, localize('website', "Website"));
}
private createInputBoxHelper(container: HTMLElement, label: string): InputBox {
const inputContainer = append(container, $('.dialog-input-section'));
append(inputContainer, $('.dialog-label')).innerText = label;
const inputCellContainer = append(inputContainer, $('.dialog-input'));
return new InputBox(inputCellContainer, this._contextViewService, {
ariaLabel: label
});
}
private registerListeners(): void {
// Theme styler
this._register(attachButtonStyler(this._copyAndOpenButton, this._themeService));
this._register(attachButtonStyler(this._closeButton, this._themeService));
this._register(attachInputBoxStyler(this._userCodeInputBox, this._themeService));
this._register(attachInputBoxStyler(this._websiteInputBox, this._themeService));
}
/* Overwrite escape key behavior */
protected onClose() {
this.cancel();
}
/* Overwrite enter key behavior */
protected onAccept() {
this.addAccount();
}
private addAccount() {
if (this._copyAndOpenButton.enabled) {
this._copyAndOpenButton.enabled = false;
this.spinner = true;
this._onHandleAddAccount.fire();
}
}
public cancel() {
this._onCancel.fire();
}
public close() {
this._copyAndOpenButton.enabled = true;
this._onCloseEvent.fire();
this.spinner = false;
this.hide();
}
public open(title: string, message: string, userCode: string, uri: string) {
// Update dialog
this.title = title;
this._descriptionElement.innerText = message;
this._userCodeInputBox.value = userCode;
this._websiteInputBox.value = uri;
this.show();
this._copyAndOpenButton.focus();
}
}

View File

@@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import Severity from 'vs/base/common/severity';
import { localize } from 'vs/nls';
import { AutoOAuthDialog } from 'sql/workbench/parts/accounts/browser/autoOAuthDialog';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
export class AutoOAuthDialogController {
// MEMBER VARIABLES ////////////////////////////////////////////////////
private _autoOAuthDialog: AutoOAuthDialog;
private _providerId?: string;
private _userCode: string;
private _uri: string;
constructor(
@IInstantiationService private _instantiationService: IInstantiationService,
@IAccountManagementService private _accountManagementService: IAccountManagementService,
@IErrorMessageService private _errorMessageService: IErrorMessageService
) { }
/**
* Open auto OAuth dialog
*/
public openAutoOAuthDialog(providerId: string, title: string, message: string, userCode: string, uri: string): Thenable<void> {
if (this._providerId !== undefined) {
// If a oauth flyout is already open, return an error
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'));
}
// Create a new dialog if one doesn't exist
if (!this._autoOAuthDialog) {
this._autoOAuthDialog = this._instantiationService.createInstance(AutoOAuthDialog);
this._autoOAuthDialog.onHandleAddAccount(this.handleOnAddAccount, this);
this._autoOAuthDialog.onCancel(this.handleOnCancel, this);
this._autoOAuthDialog.onCloseEvent(this.handleOnClose, this);
this._autoOAuthDialog.render();
}
this._userCode = userCode;
this._uri = uri;
// Open the dialog
this._autoOAuthDialog.open(title, message, userCode, uri);
this._providerId = providerId;
return Promise.resolve();
}
/**
* Close auto OAuth dialog
*/
public closeAutoOAuthDialog(): void {
this._autoOAuthDialog.close();
this._providerId = undefined;
}
// PRIVATE HELPERS /////////////////////////////////////////////////////
private handleOnCancel(): void {
this._accountManagementService.cancelAutoOAuthDeviceCode(this._providerId!); // this should be always true
}
private handleOnClose(): void {
this._providerId = undefined;
}
private handleOnAddAccount(): void {
this._accountManagementService.copyUserCodeAndOpenBrowser(this._userCode, this._uri);
}
}

View File

@@ -0,0 +1,305 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/firewallRuleDialog';
import * as DOM from 'vs/base/browser/dom';
import { Event, Emitter } from 'vs/base/common/event';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { localize } from 'vs/nls';
import { buttonBackground } from 'vs/platform/theme/common/colorRegistry';
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { URI } from 'vs/base/common/uri';
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/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/workbench/parts/accounts/browser/accountPicker';
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
import { ILogService } from 'vs/platform/log/common/log';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
import { IOpenerService } from 'vs/platform/opener/common/opener';
// TODO: Make the help link 1) extensible (01/08/2018, https://github.com/Microsoft/azuredatastudio/issues/450)
// in case that other non-Azure sign in is to be used
const firewallHelpUri = 'https://aka.ms/sqlopsfirewallhelp';
const LocalizedStrings = {
FROM: localize('from', "From"),
TO: localize('to', "To")
};
export class FirewallRuleDialog extends Modal {
public viewModel: FirewallRuleViewModel;
private _createButton: Button;
private _closeButton: Button;
private _fromRangeinputBox: InputBox;
private _toRangeinputBox: InputBox;
private _helpLink: HTMLElement;
private _IPAddressInput: HTMLElement;
private _subnetIPRangeInput: HTMLElement;
private _IPAddressElement: HTMLElement;
// EVENTING ////////////////////////////////////////////////////////////
private _onAddAccountErrorEmitter: Emitter<string>;
public get onAddAccountErrorEvent(): Event<string> { return this._onAddAccountErrorEmitter.event; }
private _onCancel: Emitter<void>;
public get onCancel(): Event<void> { return this._onCancel.event; }
private _onCreateFirewallRule: Emitter<void>;
public get onCreateFirewallRule(): Event<void> { return this._onCreateFirewallRule.event; }
constructor(
@IAccountPickerService private _accountPickerService: IAccountPickerService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IThemeService themeService: IThemeService,
@IInstantiationService private _instantiationService: IInstantiationService,
@IContextViewService private _contextViewService: IContextViewService,
@ITelemetryService telemetryService: ITelemetryService,
@IContextKeyService contextKeyService: IContextKeyService,
@IClipboardService clipboardService: IClipboardService,
@ILogService logService: ILogService,
@ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService,
@IOpenerService private readonly openerService: IOpenerService
) {
super(
localize('createNewFirewallRule', "Create new firewall rule"),
TelemetryKeys.FireWallRule,
telemetryService,
layoutService,
clipboardService,
themeService,
logService,
textResourcePropertiesService,
contextKeyService,
{
isFlyout: true,
hasBackButton: true,
hasSpinner: true
}
);
// Setup event emitters
this._onAddAccountErrorEmitter = new Emitter<string>();
this._onCancel = new Emitter<void>();
this._onCreateFirewallRule = new Emitter<void>();
this.viewModel = this._instantiationService.createInstance(FirewallRuleViewModel);
}
public render() {
super.render();
attachModalDialogStyler(this, this._themeService);
this.backButton.onDidClick(() => this.cancel());
this._register(attachButtonStyler(this.backButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND }));
this._createButton = this.addFooterButton(localize('firewall.ok', "OK"), () => this.createFirewallRule());
this._closeButton = this.addFooterButton(localize('firewall.cancel', "Cancel"), () => this.cancel());
this.registerListeners();
}
protected renderBody(container: HTMLElement) {
const body = DOM.append(container, DOM.$('.firewall-rule-dialog'));
const descriptionSection = DOM.append(body, DOM.$('.firewall-rule-description-section.new-section'));
DOM.append(descriptionSection, DOM.$('div.firewall-rule-icon'));
const textDescriptionContainer = DOM.append(descriptionSection, DOM.$('div.firewall-rule-description'));
const dialogDescription = localize('firewallRuleDialogDescription',
"Your client IP address does not have access to the server. Sign in to an Azure account and create a new firewall rule to enable access.");
this.createLabelElement(textDescriptionContainer, dialogDescription, false);
this._helpLink = DOM.append(textDescriptionContainer, DOM.$('a.help-link'));
this._helpLink.setAttribute('href', firewallHelpUri);
this._helpLink.innerHTML += localize('firewallRuleHelpDescription', "Learn more about firewall settings");
this._helpLink.onclick = () => {
this.openerService.open(URI.parse(firewallHelpUri));
};
// Create account picker with event handling
this._accountPickerService.addAccountCompleteEvent(() => this.spinner = false);
this._accountPickerService.addAccountErrorEvent((msg) => {
this.spinner = false;
this._onAddAccountErrorEmitter.fire(msg);
});
this._accountPickerService.addAccountStartEvent(() => this.spinner = true);
this._accountPickerService.onAccountSelectionChangeEvent((account) => this.onAccountSelectionChange(account));
const azureAccountSection = DOM.append(body, DOM.$('.azure-account-section.new-section'));
const azureAccountLabel = localize('azureAccount', "Azure account");
this.createLabelElement(azureAccountSection, azureAccountLabel, true);
this._accountPickerService.renderAccountPicker(DOM.append(azureAccountSection, DOM.$('.dialog-input')));
const firewallRuleSection = DOM.append(body, DOM.$('.firewall-rule-section.new-section'));
const firewallRuleLabel = localize('filewallRule', "Firewall rule");
this.createLabelElement(firewallRuleSection, firewallRuleLabel, true);
const radioContainer = DOM.append(firewallRuleSection, DOM.$('.radio-section'));
const form = DOM.append(radioContainer, DOM.$('form.firewall-rule'));
const IPAddressDiv = DOM.append(form, DOM.$('div.firewall-ip-address dialog-input'));
const subnetIPRangeDiv = DOM.append(form, DOM.$('div.firewall-subnet-ip-range dialog-input'));
const IPAddressContainer = DOM.append(IPAddressDiv, DOM.$('div.option-container'));
this._IPAddressInput = DOM.append(IPAddressContainer, DOM.$('input.option-input'));
this._IPAddressInput.setAttribute('type', 'radio');
this._IPAddressInput.setAttribute('name', 'firewallRuleChoice');
this._IPAddressInput.setAttribute('value', 'ipAddress');
const IPAddressDescription = DOM.append(IPAddressContainer, DOM.$('div.option-description'));
IPAddressDescription.innerText = localize('addIPAddressLabel', "Add my client IP ");
this._IPAddressElement = DOM.append(IPAddressContainer, DOM.$('div.option-ip-address'));
const subnetIpRangeContainer = DOM.append(subnetIPRangeDiv, DOM.$('div.option-container'));
this._subnetIPRangeInput = DOM.append(subnetIpRangeContainer, DOM.$('input.option-input'));
this._subnetIPRangeInput.setAttribute('type', 'radio');
this._subnetIPRangeInput.setAttribute('name', 'firewallRuleChoice');
this._subnetIPRangeInput.setAttribute('value', 'ipRange');
const subnetIPRangeDescription = DOM.append(subnetIpRangeContainer, DOM.$('div.option-description'));
subnetIPRangeDescription.innerText = localize('addIpRangeLabel', "Add my subnet IP range");
const subnetIPRangeSection = DOM.append(subnetIPRangeDiv, DOM.$('.subnet-ip-range-input'));
const inputContainer = DOM.append(subnetIPRangeSection, DOM.$('.dialog-input-section'));
DOM.append(inputContainer, DOM.$('.dialog-label')).innerText = LocalizedStrings.FROM;
this._fromRangeinputBox = new InputBox(DOM.append(inputContainer, DOM.$('.dialog-input')), this._contextViewService, {
ariaLabel: LocalizedStrings.FROM
});
DOM.append(inputContainer, DOM.$('.dialog-label')).innerText = LocalizedStrings.TO;
this._toRangeinputBox = new InputBox(DOM.append(inputContainer, DOM.$('.dialog-input')), this._contextViewService, {
ariaLabel: LocalizedStrings.TO
});
this._register(this._themeService.onThemeChange(e => this.updateTheme(e)));
this.updateTheme(this._themeService.getTheme());
this._register(DOM.addDisposableListener(this._IPAddressElement, DOM.EventType.CLICK, () => {
this.onFirewallRuleOptionSelected(true);
}));
this._register(DOM.addDisposableListener(this._subnetIPRangeInput, DOM.EventType.CLICK, () => {
this.onFirewallRuleOptionSelected(false);
}));
}
private onFirewallRuleOptionSelected(isIPAddress: boolean) {
this.viewModel.isIPAddressSelected = isIPAddress;
if (this._fromRangeinputBox) {
isIPAddress ? this._fromRangeinputBox.disable() : this._fromRangeinputBox.enable();
}
if (this._toRangeinputBox) {
isIPAddress ? this._toRangeinputBox.disable() : this._toRangeinputBox.enable();
}
}
protected layout(height?: number): void {
// Nothing currently laid out statically in this class
}
private createLabelElement(container: HTMLElement, content: string, isHeader?: boolean) {
let className = 'dialog-label';
if (isHeader) {
className += ' header';
}
DOM.append(container, DOM.$(`.${className}`)).innerText = content;
}
// Update theming that is specific to firewall rule flyout body
private updateTheme(theme: ITheme): void {
const linkColor = theme.getColor(buttonBackground);
const link = linkColor ? linkColor.toString() : null;
if (this._helpLink) {
this._helpLink.style.color = link;
}
}
private registerListeners(): void {
// Theme styler
this._register(attachButtonStyler(this._createButton, this._themeService));
this._register(attachButtonStyler(this._closeButton, this._themeService));
this._register(attachInputBoxStyler(this._fromRangeinputBox, this._themeService));
this._register(attachInputBoxStyler(this._toRangeinputBox, this._themeService));
// handler for from subnet ip range change events
this._register(this._fromRangeinputBox.onDidChange(IPAddress => {
this.fromRangeInputChanged(IPAddress);
}));
// handler for to subnet ip range change events
this._register(this._toRangeinputBox.onDidChange(IPAddress => {
this.toRangeInputChanged(IPAddress);
}));
}
private fromRangeInputChanged(IPAddress: string) {
this.viewModel.fromSubnetIPRange = IPAddress;
}
private toRangeInputChanged(IPAddress: string) {
this.viewModel.toSubnetIPRange = IPAddress;
}
/* Overwrite esapce key behavior */
protected onClose() {
this.cancel();
}
/* Overwrite enter key behavior */
protected onAccept() {
this.createFirewallRule();
}
public cancel() {
this._onCancel.fire();
this.close();
}
public close() {
this.hide();
}
public createFirewallRule() {
if (this._createButton.enabled) {
this._createButton.enabled = false;
this.spinner = true;
this._onCreateFirewallRule.fire();
}
}
public onAccountSelectionChange(account: azdata.Account | undefined): void {
this.viewModel.selectedAccount = account;
if (account && !account.isStale) {
this._createButton.enabled = true;
} else {
this._createButton.enabled = false;
}
}
public onServiceComplete() {
this._createButton.enabled = true;
this.spinner = false;
}
public open() {
this._IPAddressInput.click();
this.onAccountSelectionChange(this._accountPickerService.selectedAccount);
this._fromRangeinputBox.setPlaceHolder(this.viewModel.defaultFromSubnetIPRange);
this._toRangeinputBox.setPlaceHolder(this.viewModel.defaultToSubnetIPRange);
this._IPAddressElement.innerText = '(' + this.viewModel.defaultIPAddress + ')';
this.show();
}
}

View File

@@ -0,0 +1,94 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
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/workbench/parts/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';
export class FirewallRuleDialogController {
private _firewallRuleDialog: FirewallRuleDialog;
private _connection: IConnectionProfile;
private _resourceProviderId: string;
private _addAccountErrorTitle = localize('firewallDialog.addAccountErrorTitle', "Error adding account");
private _firewallRuleErrorTitle = localize('firewallRuleError', "Firewall rule error");
private _deferredPromise: Deferred<boolean>;
constructor(
@IInstantiationService private _instantiationService: IInstantiationService,
@IResourceProviderService private _resourceProviderService: IResourceProviderService,
@IAccountManagementService private _accountManagementService: IAccountManagementService,
@IErrorMessageService private _errorMessageService: IErrorMessageService
) {
}
/**
* Open firewall rule dialog
*/
public openFirewallRuleDialog(connection: IConnectionProfile, ipAddress: string, resourceProviderId: string): Promise<boolean> {
if (!this._firewallRuleDialog) {
this._firewallRuleDialog = this._instantiationService.createInstance(FirewallRuleDialog);
this._firewallRuleDialog.onCancel(this.handleOnCancel, this);
this._firewallRuleDialog.onCreateFirewallRule(this.handleOnCreateFirewallRule, this);
this._firewallRuleDialog.onAddAccountErrorEvent(this.handleOnAddAccountError, this);
this._firewallRuleDialog.render();
}
this._connection = connection;
this._resourceProviderId = resourceProviderId;
this._firewallRuleDialog.viewModel.updateDefaultValues(ipAddress);
this._firewallRuleDialog.open();
this._deferredPromise = new Deferred();
return this._deferredPromise.promise;
}
// PRIVATE HELPERS /////////////////////////////////////////////////////
private handleOnAddAccountError(message: string): void {
this._errorMessageService.showDialog(Severity.Error, this._addAccountErrorTitle, message);
}
private async handleOnCreateFirewallRule(): Promise<void> {
const resourceProviderId = this._resourceProviderId;
try {
const securityTokenMappings = await this._accountManagementService.getSecurityToken(this._firewallRuleDialog.viewModel.selectedAccount!, AzureResource.ResourceManagement);
const firewallRuleInfo: azdata.FirewallRuleInfo = {
startIpAddress: this._firewallRuleDialog.viewModel.isIPAddressSelected ? this._firewallRuleDialog.viewModel.defaultIPAddress : this._firewallRuleDialog.viewModel.fromSubnetIPRange,
endIpAddress: this._firewallRuleDialog.viewModel.isIPAddressSelected ? this._firewallRuleDialog.viewModel.defaultIPAddress : this._firewallRuleDialog.viewModel.toSubnetIPRange,
serverName: this._connection.serverName,
securityTokenMappings
};
const response = await this._resourceProviderService.createFirewallRule(this._firewallRuleDialog.viewModel.selectedAccount!, firewallRuleInfo, resourceProviderId);
if (response.result) {
this._firewallRuleDialog.close();
this._deferredPromise.resolve(true);
} else {
this._errorMessageService.showDialog(Severity.Error, this._firewallRuleErrorTitle, response.errorMessage);
}
this._firewallRuleDialog.onServiceComplete();
} catch (e) {
this.showError(e);
}
}
private showError(error: any): void {
this._errorMessageService.showDialog(Severity.Error, this._firewallRuleErrorTitle, error);
this._firewallRuleDialog.onServiceComplete();
// Note: intentionally not rejecting the promise as we want users to be able to choose a different account
}
private handleOnCancel(): void {
this._deferredPromise.resolve(false);
}
}

View File

@@ -0,0 +1,14 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* Icons for various account actions */
.vs .action-item .codicon.add-linked-account-action {
background-image: url('new_account.svg');
}
.vs-dark .action-item .codicon.add-linked-account-action,
.hc-black .action-item .codicon.add-linked-account-action {
background-image: url('new_account_inverse.svg');
}

View File

@@ -0,0 +1,105 @@
/*---------------------------------------------------------------------------------------------
* 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;
}
.no-account-view .no-account-view-label {
padding-bottom: 15px;
}
.account-view .header {
position: relative;
line-height: 22px;
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
padding-left: 20px;
padding-right: 12px;
overflow: hidden;
display: flex;
}
.account-view .header .title {
display: flex;
justify-content: flex-start;
flex: 1 1 auto;
}
.account-view .header .actions {
display: flex;
justify-content: flex-end;
}
.account-view .header .actions .action-item .action-label {
width: 30px;
background-size: 16px;
background-position: center center;
background-repeat: no-repeat;
margin-right: 0;
height: 22px;
}
.account-view .header .count-badge-wrapper {
justify-content: flex-end;
/* hide the count badge as it is not providing much value and meanwhile not keyboard accessible*/
display: none;
}
.account-view .list-row {
padding: 12px;
line-height: 18px !important;
}
.account-view .list-row .codicon {
flex: 0 0 50px;
height: 50px;
width: 50px;
background-size: 50px;
}
.account-view .list-row .codicon .badge {
position: absolute;
top: 43px;
left: 43px;
overflow: hidden;
width: 22px;
height: 22px;
}
.account-view .list-row .codicon .badge .badge-content {
width: 22px;
height: 22px;
background-size: 22px;
}
.account-view .list-row .actions-container {
flex: 0 0 50px;
}
.account-view .list-row .actions-container .action-item .action-label {
width: 16px;
margin-left: 20px;
margin-right: 10px;
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
}
.account-view .list-row .actions-container .action-item .action-label.codicon.remove {
background-size: 14px !important;
}
.account-view .list-row .actions-container {
display: none;
}
.account-view .monaco-list .monaco-list-row:hover .list-row .actions-container,
.account-view .monaco-list .monaco-list-row.selected .list-row .actions-container,
.account-view .monaco-list .monaco-list-row.focused .list-row .actions-container{
display: block;
}

View File

@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.list-row.account-picker-list {
display: flex;
align-items: flex-start;
}
.list-row.account-picker-list .label {
flex: 1 1 auto;
margin-left: 15px;
}
.list-row.account-picker-list .label .contextual-display-name {
font-size: 15px;
line-height: 15px;
}
.list-row.account-picker-list .label .display-name {
font-size: 13px;
line-height: 13px;
}
.list-row.account-picker-list .label .content {
opacity: 0.7;
}
.account-logo {
background: no-repeat center center;
}

View File

@@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.statusbar-item .linked-account-staus a.linked-account-status-selection .linked-account-icon {
-webkit-mask: url('accounts_statusbar_inverse.svg') no-repeat 50% 50%;
-webkit-mask-size: 12px;
width: 12px;
height: 22px;
}
.statusbar-item .linked-account-staus a.linked-account-status-selection {
padding: 0 5px 0 5px;
}

View File

@@ -0,0 +1,99 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* Selected account */
.selected-account-container {
padding: 6px;
display: flex;
align-items: flex-start;
}
.selected-account-container .codicon {
flex: 0 0 25px;
height: 25px;
width: 25px;
}
.selected-account-container .label {
flex: 1 1 auto;
padding-left: 10px;
align-self: center;
}
.selected-account-container .codicon {
background-size: 25px;
}
.selected-account-container .codicon .badge {
position: relative;
top: 15px;
left: 15px;
overflow: hidden;
width: 12px;
height: 12px;
}
.selected-account-container .codicon .badge .badge-content {
width: 12px;
height: 12px;
background-size: 12px;
}
/* A container when the account list is empty */
.no-account-container {
padding: 6px;
opacity: 0.7;
font-style: italic;
}
/* Account list */
.account-list-container .list-row {
padding: 6px;
}
.account-list-container .list-row .codicon {
flex: 0 0 35px;
height: 35px;
width: 35px;
background-size: 35px;
}
.account-list-container .list-row .codicon .badge {
position: relative;
top: 22px;
left: 22px;
overflow: hidden;
width: 15px;
height: 15px;
}
.account-list-container .list-row .codicon .badge .badge-content {
width: 15px;
height: 15px;
background-size: 15px;
}
/* Refresh link */
.refresh-container {
padding-left: 15px;
padding-top: 6px;
display: flex;
align-items: flex-start;
}
.refresh-container .monaco-action-bar .actions-container {
justify-content: flex-start;
}
.refresh-container .codicon {
flex: 0 0 16px;
height: 16px;
width: 16px;
}
.refresh-container .monaco-action-bar {
flex: 1 1 auto;
margin-left: 10px;
}

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11 10.89"><defs><style>.cls-1{fill:#fff;}</style></defs><title>accounts_statusbar_inverse_11x11</title><path class="cls-1" d="M10.08,5.66a3.44,3.44,0,0,0-.34-.75,3.47,3.47,0,0,0-.52-.64A3.23,3.23,0,0,0,8.8,4a2.28,2.28,0,0,0,.7-1.65,2.27,2.27,0,0,0-.18-.89A2.31,2.31,0,0,0,8.09.19,2.19,2.19,0,0,0,7.19,0,2.16,2.16,0,0,0,6.3.19a2.41,2.41,0,0,0-.73.49,2.41,2.41,0,0,0-.49.73,2.16,2.16,0,0,0-.19.89,2.22,2.22,0,0,0,.25,1A2.31,2.31,0,0,0,5.58,4a3.62,3.62,0,0,0-.52.41,3.62,3.62,0,0,0-.41.52A2.31,2.31,0,0,0,4,4.44a2.26,2.26,0,0,0-1-.25,2.16,2.16,0,0,0-.89.19,2.41,2.41,0,0,0-.73.49,2.41,2.41,0,0,0-.49.73,2.16,2.16,0,0,0-.19.89,2.22,2.22,0,0,0,.25,1,2.31,2.31,0,0,0,.45.61A3.7,3.7,0,0,0,1,8.47a3.47,3.47,0,0,0-.52.64,2.88,2.88,0,0,0-.34.75,3.06,3.06,0,0,0-.12.83v.21H1.12v-.21A1.83,1.83,0,0,1,1.27,10a1.9,1.9,0,0,1,1-1A1.83,1.83,0,0,1,3,8.8a1.86,1.86,0,0,1,.73.15,2,2,0,0,1,.6.4,1.9,1.9,0,0,1,.4.6,1.85,1.85,0,0,1,.15.73v.21H6v-.21a3.05,3.05,0,0,0-.11-.83,3.44,3.44,0,0,0-.34-.75A3.25,3.25,0,0,0,5,8.47a3.23,3.23,0,0,0-.43-.32,2.28,2.28,0,0,0,.7-1.65,1.83,1.83,0,0,1,.15-.73,1.9,1.9,0,0,1,1-1,1.83,1.83,0,0,1,.73-.15,1.86,1.86,0,0,1,.73.15,1.9,1.9,0,0,1,1,1,1.82,1.82,0,0,1,.15.73V6.7h1.12V6.49A3.05,3.05,0,0,0,10.08,5.66ZM4.1,7a1.24,1.24,0,0,1-.64.64A1.13,1.13,0,0,1,3,7.68a1.1,1.1,0,0,1-.45-.09,1.21,1.21,0,0,1-.38-.26A1.1,1.1,0,0,1,1.91,7a1.11,1.11,0,0,1-.1-.46A1.13,1.13,0,0,1,1.91,6a1.1,1.1,0,0,1,.26-.38,1.1,1.1,0,0,1,.38-.26A1.1,1.1,0,0,1,3,5.31a1.16,1.16,0,0,1,.46.1A1.24,1.24,0,0,1,4.1,6a1.15,1.15,0,0,1,.09.45A1.13,1.13,0,0,1,4.1,7ZM8.29,2.76a1.24,1.24,0,0,1-.64.64,1.13,1.13,0,0,1-.46.09,1.1,1.1,0,0,1-.45-.09,1.21,1.21,0,0,1-.38-.26,1.1,1.1,0,0,1-.26-.38A1.14,1.14,0,0,1,6,2.3a1.15,1.15,0,0,1,.1-.45,1.1,1.1,0,0,1,.26-.38,1.19,1.19,0,0,1,.83-.36,1.16,1.16,0,0,1,.46.1A1.1,1.1,0,0,1,8,1.47a1.21,1.21,0,0,1,.26.38,1.15,1.15,0,0,1,.09.45A1.13,1.13,0,0,1,8.29,2.76Z"/></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.auto-oauth-dialog {
padding: 15px
}
.modal .auto-oauth-dialog .new-section {
padding-bottom: 30px;
}
.modal .auto-oauth-dialog .dialog-input-section {
display: flex;
padding-left: 15px;
padding-right: 15px;
padding-top: 10px;
padding-bottom: 10px;
}
.modal .auto-oauth-dialog .dialog-input-section .dialog-label {
flex: 0 0 100px;
align-self: center;
}
.modal .auto-oauth-dialog .dialog-input-section .dialog-input {
flex: 1 1 auto;
}

View File

@@ -0,0 +1,86 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.firewall-rule-dialog {
padding: 15px
}
.modal .firewall-rule-dialog .dialog-label.header {
font-size: 15px;
}
.modal .firewall-rule-dialog .new-section {
padding-bottom: 30px;
}
.modal .firewall-rule-dialog .dialog-input {
padding-left: 15px;
padding-right: 15px;
padding-top: 10px;
}
.modal .firewall-rule-dialog .dialog-input-section {
display: flex;
padding-left: 30px;
padding-right: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
.modal .firewall-rule-dialog .dialog-input-section .dialog-label {
flex: 0 0 15px;
align-self: center;
}
.modal .firewall-rule-dialog .dialog-input-section .dialog-input {
flex: 0 0 100px;
padding-left: 10px;
padding-right: 10px;
padding-top: 0px;
padding-bottom: 0px;
}
.modal .firewall-rule-dialog .azure-account-section {
height: 92px;
}
/* Firewall rule description section */
.modal .firewall-rule-dialog a:link {
text-decoration: underline;
}
.modal .firewall-rule-dialog .firewall-rule-description-section {
display: flex;
}
.modal .firewall-rule-dialog .firewall-rule-description-section .firewall-rule-icon {
background: url('secure.svg') center center no-repeat;
width: 50px;
height: 50px;
flex: 0 0 50px;
}
.modal .firewall-rule-dialog .firewall-rule-description-section .firewall-rule-description {
padding-left: 15px;
}
/* Radio button section*/
.modal .firewall-rule-dialog .firewall-rule-section .radio-section .option-container {
display: flex;
align-items: flex-start;
}
.modal .firewall-rule-dialog .firewall-rule-section .radio-section .option-container .option-input {
margin-top: 0px;
align-self: center;
}
.modal .firewall-rule-dialog .firewall-rule-section .radio-section .option-container .option-description {
padding-left: 10px;
}
.modal .firewall-rule-dialog .firewall-rule-section .radio-section .option-container .option-ip-address {
padding-left: 3px;
}

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>new_account_16x16</title><path d="M8.09,7.39a5.91,5.91,0,0,1,1.38.74,6.06,6.06,0,0,1,1.13,1.06A6,6,0,0,1,11.88,12h-1a4.94,4.94,0,0,0-.63-1.61A5,5,0,0,0,7.66,8.3a5,5,0,0,0-3-.12,5.09,5.09,0,0,0-1.2.5,5,5,0,0,0-1.79,1.79,5.07,5.07,0,0,0-.5,1.2A4.88,4.88,0,0,0,1,13H0a5.88,5.88,0,0,1,.28-1.8A6,6,0,0,1,1,9.59a6.1,6.1,0,0,1,1.22-1.3,5.8,5.8,0,0,1,1.59-.9A4.2,4.2,0,0,1,2.46,5.94,3.86,3.86,0,0,1,2,4a3.92,3.92,0,0,1,.31-1.56A4,4,0,0,1,4.4.31a4,4,0,0,1,3.12,0A4,4,0,0,1,9.65,2.44,4,4,0,0,1,9.83,5a4,4,0,0,1-1,1.74A3.94,3.94,0,0,1,8.09,7.39ZM3,4A2.92,2.92,0,0,0,3.2,5.17a3,3,0,0,0,1.6,1.6,3,3,0,0,0,2.33,0,3,3,0,0,0,1.6-1.6,3,3,0,0,0,0-2.33,3,3,0,0,0-1.6-1.6,3,3,0,0,0-2.33,0,3,3,0,0,0-1.6,1.6A2.92,2.92,0,0,0,3,4Zm13,9v1H14v2H13V14H11V13h2V11h1v2Z"/></svg>

After

Width:  |  Height:  |  Size: 850 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}</style></defs><title>new_account_inverse_16x16</title><path class="cls-1" d="M8.13,7.39a5.91,5.91,0,0,1,1.38.74,6.06,6.06,0,0,1,1.13,1.06A6,6,0,0,1,11.91,12h-1a4.94,4.94,0,0,0-.63-1.61A5,5,0,0,0,7.7,8.3a5,5,0,0,0-3-.12,5.09,5.09,0,0,0-1.2.5,5,5,0,0,0-1.79,1.79,5.07,5.07,0,0,0-.5,1.2A4.88,4.88,0,0,0,1,13H0a5.88,5.88,0,0,1,.28-1.8,6,6,0,0,1,.79-1.6,6.1,6.1,0,0,1,1.22-1.3,5.8,5.8,0,0,1,1.59-.9A4.2,4.2,0,0,1,2.5,5.94,3.86,3.86,0,0,1,2,4a3.92,3.92,0,0,1,.31-1.56A4,4,0,0,1,4.44.31a4,4,0,0,1,3.12,0A4,4,0,0,1,9.69,2.44,4,4,0,0,1,9.87,5a4,4,0,0,1-1,1.74A3.94,3.94,0,0,1,8.13,7.39ZM3,4a2.92,2.92,0,0,0,.23,1.17,3,3,0,0,0,1.6,1.6,3,3,0,0,0,2.33,0,3,3,0,0,0,1.6-1.6,3,3,0,0,0,0-2.33,3,3,0,0,0-1.6-1.6,3,3,0,0,0-2.33,0,3,3,0,0,0-1.6,1.6A2.92,2.92,0,0,0,3,4Zm13,9v1H14v2H13V14H11V13h2V11h1v2Z"/></svg>

After

Width:  |  Height:  |  Size: 918 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36.65 50"><defs><style>.cls-1{fill:#7fba00;}.cls-2{fill:#b8d432;opacity:0.4;isolation:isolate;}.cls-3{fill:#fff;}</style></defs><title>secure</title><path class="cls-1" d="M31.19,6h0c-11-1.22-12.86-6-12.86-6S15.85,6.24,0,6.24V31.85c0,3.1,1.72,6,4.1,8.53h0C9.51,46.13,18.33,50,18.33,50s18.33-8,18.33-18.15V6.24A49.77,49.77,0,0,1,31.19,6Z"/><path class="cls-2" d="M22.86,16.54,31.19,6c-11-1.22-12.86-6-12.86-6S15.85,6.24,0,6.24V31.85c0,3.1,1.72,6,4.1,8.53l6.15-7.82Z"/><path class="cls-3" d="M25.6,24.46H24.53V20.91a6.7,6.7,0,0,0-1.67-4.45h0l-.11-.13a6,6,0,0,0-8.84,0,6.7,6.7,0,0,0-1.78,4.58v3.55H11.06a.8.8,0,0,0-.8.8v7.22h0v2.17a.8.8,0,0,0,.8.8H25.6a.8.8,0,0,0,.8-.8V25.26A.8.8,0,0,0,25.6,24.46Zm-4,0H15.07V20.91a3.75,3.75,0,0,1,1-2.57,3,3,0,0,1,4.54,0,3.67,3.67,0,0,1,.39.5h0a3.8,3.8,0,0,1,.6,2.06Z"/></svg>

After

Width:  |  Height:  |  Size: 894 B

View File

@@ -0,0 +1,103 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as TypeMoq from 'typemoq';
import { Emitter } from 'vs/base/common/event';
import { AccountDialog } from 'sql/workbench/parts/accounts/browser/accountDialog';
import { AccountDialogController } from 'sql/workbench/parts/accounts/browser/accountDialogController';
import { AccountViewModel } from 'sql/platform/accounts/common/accountViewModel';
import { TestAccountManagementService } from 'sql/platform/accounts/test/common/testAccountManagementService';
import { TestErrorMessageService } from 'sql/platform/errorMessage/test/common/testErrorMessageService';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { AccountListRenderer } from 'sql/workbench/parts/accounts/browser/accountListRenderer';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
// TESTS ///////////////////////////////////////////////////////////////////
suite('Account Management Dialog Controller Tests', () => {
test('Open Account Dialog - Dialog Doesn\'t Exist', () => {
// Setup: Create instance of the controller
let instantiationService = createInstantiationService();
let controller = new AccountDialogController(instantiationService, undefined!);
assert.strictEqual(controller.accountDialog, undefined);
// If: I open the account dialog when one hasn't been opened
controller.openAccountDialog();
// Then:
// ... The account dialog should be defined
assert.notStrictEqual(controller.accountDialog, undefined);
});
test('Open Account Dialog - Dialog Exists', () => {
// Setup: Create instance of the controller with an account dialog already loaded
let instantiationService = createInstantiationService();
let controller = new AccountDialogController(instantiationService, undefined!);
controller.openAccountDialog();
let accountDialog = controller.accountDialog;
// If: I open the account dialog when one has already been opened
controller.openAccountDialog();
// Then: It should be the same dialog that already existed
assert.equal(controller.accountDialog, accountDialog);
});
test('Add Account Failure - Error Message Shown', () => {
// Setup:
// ... Create instantiation service that returns mock emitter for account dialog
let mockEventEmitter = new Emitter<string>();
let instantiationService = createInstantiationService(mockEventEmitter);
// ... Create a mock instance of the error message service
let errorMessageServiceStub = new TestErrorMessageService();
let mockErrorMessageService = TypeMoq.Mock.ofInstance(errorMessageServiceStub);
mockErrorMessageService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()));
// ... Create instance of the controller with an opened dialog
let controller = new AccountDialogController(instantiationService, mockErrorMessageService.object);
controller.openAccountDialog();
// If: The account dialog reports a failure adding an account
mockEventEmitter.fire('Error message');
// Then: An error dialog should have been opened
mockErrorMessageService.verify(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
});
});
function createInstantiationService(addAccountFailureEmitter?: Emitter<string>): InstantiationService {
// Create a mock account dialog view model
let accountViewModel = new AccountViewModel(new TestAccountManagementService());
let mockAccountViewModel = TypeMoq.Mock.ofInstance(accountViewModel);
let mockEvent = new Emitter<any>();
mockAccountViewModel.setup(x => x.addProviderEvent).returns(() => mockEvent.event);
mockAccountViewModel.setup(x => x.removeProviderEvent).returns(() => mockEvent.event);
mockAccountViewModel.setup(x => x.updateAccountListEvent).returns(() => mockEvent.event);
mockAccountViewModel.setup(x => x.initialize()).returns(() => Promise.resolve([]));
// Create a mocked out instantiation service
let instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Strict);
instantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(AccountViewModel)))
.returns(() => mockAccountViewModel.object);
instantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(AccountListRenderer)))
.returns(() => undefined);
// Create a mock account dialog
let accountDialog = new AccountDialog(undefined!, undefined!, instantiationService.object, undefined!, undefined!, undefined!, undefined!, new MockContextKeyService(), undefined!, undefined!, undefined!);
let mockAccountDialog = TypeMoq.Mock.ofInstance(accountDialog);
mockAccountDialog.setup(x => x.onAddAccountErrorEvent)
.returns(() => { return addAccountFailureEmitter ? addAccountFailureEmitter.event : mockEvent.event; });
mockAccountDialog.setup(x => x.onCloseEvent)
.returns(() => mockEvent.event);
mockAccountDialog.setup(x => x.render())
.returns(() => undefined);
mockAccountDialog.setup(x => x.open())
.returns(() => undefined);
instantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(AccountDialog)))
.returns(() => mockAccountDialog.object);
return instantiationService.object;
}

View File

@@ -0,0 +1,122 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as assert from 'assert';
import * as TypeMoq from 'typemoq';
import { EventVerifierSingle } from 'sql/base/test/common/event';
import { Emitter } from 'vs/base/common/event';
import { AccountPicker } from 'sql/workbench/parts/accounts/browser/accountPickerImpl';
import { AccountPickerService } from 'sql/workbench/parts/accounts/browser/accountPickerService';
import { AccountPickerViewModel } from 'sql/platform/accounts/common/accountPickerViewModel';
import { TestAccountManagementService } from 'sql/platform/accounts/test/common/testAccountManagementService';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
// SUITE STATE /////////////////////////////////////////////////////////////
let mockAddAccountCompleteEmitter: Emitter<void>;
let mockAddAccountErrorEmitter: Emitter<string>;
let mockAddAccountStartEmitter: Emitter<void>;
let mockOnAccountSelectionChangeEvent: Emitter<azdata.Account>;
// TESTS ///////////////////////////////////////////////////////////////////
suite('Account picker service tests', () => {
setup(() => {
// Setup event mocks for the account picker service
mockAddAccountCompleteEmitter = new Emitter<void>();
mockAddAccountErrorEmitter = new Emitter<string>();
mockAddAccountStartEmitter = new Emitter<void>();
mockOnAccountSelectionChangeEvent = new Emitter<azdata.Account>();
});
test('Construction - Events are properly defined', () => {
// Setup:
// ... Create instantiation service
let instantiationService = createInstantiationService();
// ... Create instance of the service and reder account picker
let service = new AccountPickerService(instantiationService);
service.renderAccountPicker(TypeMoq.It.isAny());
// Then:
// ... All the events for the view models should be properly initialized
assert.notEqual(service.addAccountCompleteEvent, undefined);
assert.notEqual(service.addAccountErrorEvent, undefined);
assert.notEqual(service.addAccountStartEvent, undefined);
assert.notEqual(service.onAccountSelectionChangeEvent, undefined);
// ... All the events should properly fire
let evAddAccountCompleteEvent = new EventVerifierSingle<void>();
service.addAccountCompleteEvent(evAddAccountCompleteEvent.eventHandler);
mockAddAccountCompleteEmitter.fire();
evAddAccountCompleteEvent.assertFired();
let errorMsg = 'Error';
let evAddAccountErrorEvent = new EventVerifierSingle<string>();
service.addAccountErrorEvent(evAddAccountErrorEvent.eventHandler);
mockAddAccountErrorEmitter.fire(errorMsg);
evAddAccountErrorEvent.assertFired(errorMsg);
let evAddAccountStartEvent = new EventVerifierSingle<void>();
service.addAccountStartEvent(evAddAccountStartEvent.eventHandler);
mockAddAccountStartEmitter.fire();
evAddAccountStartEvent.assertFired();
let account = {
key: { providerId: 'azure', accountId: 'account1' },
name: 'Account 1',
displayInfo: {
contextualDisplayName: 'Microsoft Account',
accountType: 'microsoft',
displayName: 'Account 1',
userId: 'user@email.com'
},
properties: [],
isStale: false
};
let evOnAccountSelectionChangeEvent = new EventVerifierSingle<azdata.Account>();
service.onAccountSelectionChangeEvent(evOnAccountSelectionChangeEvent.eventHandler);
mockOnAccountSelectionChangeEvent.fire(account);
evOnAccountSelectionChangeEvent.assertFired(account);
});
});
function createInstantiationService(): InstantiationService {
// Create a mock account picker view model
let providerId = 'azure';
let accountPickerViewModel = new AccountPickerViewModel(providerId, new TestAccountManagementService());
let mockAccountViewModel = TypeMoq.Mock.ofInstance(accountPickerViewModel);
let mockEvent = new Emitter<any>();
mockAccountViewModel.setup(x => x.updateAccountListEvent).returns(() => mockEvent.event);
// Create a mocked out instantiation service
let instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Strict);
instantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(AccountPickerViewModel), TypeMoq.It.isAny()))
.returns(() => mockAccountViewModel.object);
// Create a mock account picker
let accountPicker = new AccountPicker('provider', new TestThemeService(), instantiationService.object, undefined!);
let mockAccountDialog = TypeMoq.Mock.ofInstance(accountPicker);
mockAccountDialog.setup(x => x.addAccountCompleteEvent)
.returns(() => mockAddAccountCompleteEmitter.event);
mockAccountDialog.setup(x => x.addAccountErrorEvent)
.returns((msg) => mockAddAccountErrorEmitter.event);
mockAccountDialog.setup(x => x.addAccountStartEvent)
.returns(() => mockAddAccountStartEmitter.event);
mockAccountDialog.setup(x => x.onAccountSelectionChangeEvent)
.returns((account) => mockOnAccountSelectionChangeEvent.event);
mockAccountDialog.setup(x => x.render(TypeMoq.It.isAny()))
.returns((container) => undefined);
mockAccountDialog.setup(x => x.createAccountPickerComponent());
instantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(AccountPicker), TypeMoq.It.isAny()))
.returns(() => mockAccountDialog.object);
return instantiationService.object;
}

View File

@@ -0,0 +1,139 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as TypeMoq from 'typemoq';
import { Emitter } from 'vs/base/common/event';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { AutoOAuthDialog } from 'sql/workbench/parts/accounts/browser/autoOAuthDialog';
import { AutoOAuthDialogController } from 'sql/workbench/parts/accounts/browser/autoOAuthDialogController';
import { TestAccountManagementService } from 'sql/platform/accounts/test/common/testAccountManagementService';
import { TestErrorMessageService } from 'sql/platform/errorMessage/test/common/testErrorMessageService';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
// TESTS ///////////////////////////////////////////////////////////////////
suite('auto OAuth dialog controller tests', () => {
let instantiationService: TypeMoq.Mock<InstantiationService>;
let mockAutoOAuthDialog: TypeMoq.Mock<AutoOAuthDialog>;
let mockAccountManagementService: TypeMoq.Mock<TestAccountManagementService>;
let mockErrorMessageService: TypeMoq.Mock<TestErrorMessageService>;
let autoOAuthDialogController: AutoOAuthDialogController;
let mockOnCancelEvent: Emitter<void>;
let mockOnAddAccountEvent: Emitter<void>;
let mockOnCloseEvent: Emitter<void>;
let providerId = 'azure';
let title = 'Add Account';
let message = 'This is the dialog description';
let userCode = 'abcde';
let uri = 'uri';
setup(() => {
mockOnCancelEvent = new Emitter<void>();
mockOnAddAccountEvent = new Emitter<void>();
mockOnCloseEvent = new Emitter<void>();
// Create a mock auto OAuth dialog
let autoOAuthDialog = new AutoOAuthDialog(undefined!, undefined!, undefined!, undefined!, new MockContextKeyService(), undefined!, undefined!, undefined!);
mockAutoOAuthDialog = TypeMoq.Mock.ofInstance(autoOAuthDialog);
mockAutoOAuthDialog.setup(x => x.onCancel).returns(() => mockOnCancelEvent.event);
mockAutoOAuthDialog.setup(x => x.onHandleAddAccount).returns(() => mockOnAddAccountEvent.event);
mockAutoOAuthDialog.setup(x => x.onCloseEvent).returns(() => mockOnCloseEvent.event);
mockAutoOAuthDialog.setup(x => x.render());
mockAutoOAuthDialog.setup(x => x.open(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()));
mockAutoOAuthDialog.setup(x => x.close()).callback(() => {
mockOnCloseEvent.fire();
});
// Create a mocked out instantiation service
instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Strict);
instantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(AutoOAuthDialog)))
.returns(() => mockAutoOAuthDialog.object);
// Create a mocked account management service
let accountManagementTestService = new TestAccountManagementService();
mockAccountManagementService = TypeMoq.Mock.ofInstance(accountManagementTestService);
mockAccountManagementService.setup(x => x.copyUserCodeAndOpenBrowser(TypeMoq.It.isAny(), TypeMoq.It.isAny()));
// Create a mocked error message service
let errorMessageServiceStub = new TestErrorMessageService();
mockErrorMessageService = TypeMoq.Mock.ofInstance(errorMessageServiceStub);
mockErrorMessageService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()));
// Create a mocked auto OAuth dialog controller
autoOAuthDialogController = new AutoOAuthDialogController(instantiationService.object, mockAccountManagementService.object, mockErrorMessageService.object);
});
test('Open auto OAuth when the flyout is already open, return an error', (done) => {
// If: Open auto OAuth dialog first time
autoOAuthDialogController.openAutoOAuthDialog(providerId, title, message, userCode, uri);
// Then: It should open the flyout successfully
mockAutoOAuthDialog.verify(x => x.open(title, message, userCode, uri), TypeMoq.Times.once());
mockErrorMessageService.verify(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.never());
// If: a oauth flyout is already open
autoOAuthDialogController.openAutoOAuthDialog(providerId, title, message, userCode, uri)
.then(success => done('Failure: Expected error on 2nd dialog open'), error => done());
// Then: An error dialog should have been opened
mockErrorMessageService.verify(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
});
test('Close auto OAuth dialog successfully', () => {
let title = 'Add Account';
let message = 'This is the dialog description';
let userCode = 'abcde';
let uri = 'uri';
autoOAuthDialogController.openAutoOAuthDialog(providerId, title, message, userCode, uri);
// If: closeAutoOAuthDialog is called
autoOAuthDialogController.closeAutoOAuthDialog();
// Then: it should close the dialog
mockAutoOAuthDialog.verify(x => x.close(), TypeMoq.Times.once());
});
test('Open and close auto OAuth dialog multiple times should work properly', () => {
let title = 'Add Account';
let message = 'This is the dialog description';
let userCode = 'abcde';
let uri = 'uri';
autoOAuthDialogController.openAutoOAuthDialog(providerId, title, message, userCode, uri);
autoOAuthDialogController.closeAutoOAuthDialog();
// If: Open the flyout second time
autoOAuthDialogController.openAutoOAuthDialog(providerId, title, message, userCode, uri);
// Then: It should open the flyout twice successfully
mockAutoOAuthDialog.verify(x => x.open(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.exactly(2));
mockErrorMessageService.verify(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.never());
});
test('Copy and open button in auto OAuth dialog should work properly', () => {
let title = 'Add Account';
let message = 'This is the dialog description';
let userCode = 'abcde';
let uri = 'uri';
autoOAuthDialogController.openAutoOAuthDialog(providerId, title, message, userCode, uri);
// If: the 'copy & open' button in auto Oauth dialog is selected
mockOnAddAccountEvent.fire();
// Then: copyUserCodeAndOpenBrowser should get called
mockAccountManagementService.verify(x => x.copyUserCodeAndOpenBrowser(userCode, uri), TypeMoq.Times.once());
});
// TODO: Test for cancel button
});

View File

@@ -0,0 +1,249 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as TypeMoq from 'typemoq';
import { Emitter, Event } from 'vs/base/common/event';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { FirewallRuleDialog } from 'sql/workbench/parts/accounts/browser/firewallRuleDialog';
import { FirewallRuleViewModel } from 'sql/platform/accounts/common/firewallRuleViewModel';
import { FirewallRuleDialogController } from 'sql/workbench/parts/accounts/browser/firewallRuleDialogController';
import { TestAccountManagementService } from 'sql/platform/accounts/test/common/testAccountManagementService';
import { TestResourceProvider } from 'sql/workbench/services/resourceProvider/test/common/testResourceProviderService';
import { TestErrorMessageService } from 'sql/platform/errorMessage/test/common/testErrorMessageService';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { Deferred } from 'sql/base/common/promise';
import { mssqlProviderName } from 'sql/platform/connection/common/constants';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
// TESTS ///////////////////////////////////////////////////////////////////
suite('Firewall rule dialog controller tests', () => {
let connectionProfile: IConnectionProfile;
let account: azdata.Account;
let IPAddress = '250.222.155.198';
let mockOnAddAccountErrorEvent: Emitter<string>;
let mockOnCreateFirewallRule: Emitter<void>;
let instantiationService: TypeMoq.Mock<InstantiationService>;
let mockFirewallRuleViewModel: TypeMoq.Mock<FirewallRuleViewModel>;
let mockFirewallRuleDialog: TypeMoq.Mock<FirewallRuleDialog>;
setup(() => {
account = {
key: { providerId: 'azure', accountId: 'account1' },
displayInfo: {
contextualDisplayName: 'Microsoft Account',
accountType: 'microsoft',
displayName: 'Account 1',
userId: 'user@email.com'
},
properties: [],
isStale: false
};
mockOnAddAccountErrorEvent = new Emitter<string>();
mockOnCreateFirewallRule = new Emitter<void>();
// Create a mock firewall rule view model
let firewallRuleViewModel = new FirewallRuleViewModel();
mockFirewallRuleViewModel = TypeMoq.Mock.ofInstance(firewallRuleViewModel);
mockFirewallRuleViewModel.setup(x => x.updateDefaultValues(TypeMoq.It.isAny()))
.returns((ipAddress) => undefined);
mockFirewallRuleViewModel.object.selectedAccount = account;
mockFirewallRuleViewModel.object.isIPAddressSelected = true;
// Create a mocked out instantiation service
instantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Strict);
instantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(FirewallRuleViewModel)))
.returns(() => mockFirewallRuleViewModel.object);
// Create a mock account picker
let firewallRuleDialog = new FirewallRuleDialog(undefined!, undefined!, undefined!, instantiationService.object, undefined!, undefined!, new MockContextKeyService(), undefined!, undefined!, undefined!, undefined!);
mockFirewallRuleDialog = TypeMoq.Mock.ofInstance(firewallRuleDialog);
let mockEvent = new Emitter<any>();
mockFirewallRuleDialog.setup(x => x.onCancel)
.returns(() => mockEvent.event);
mockFirewallRuleDialog.setup(x => x.onCreateFirewallRule)
.returns(() => mockOnCreateFirewallRule.event);
mockFirewallRuleDialog.setup(x => x.onAddAccountErrorEvent)
.returns((msg) => mockOnAddAccountErrorEvent.event);
mockFirewallRuleDialog.setup(x => x.render());
mockFirewallRuleDialog.setup(x => x.open());
mockFirewallRuleDialog.setup(x => x.close());
instantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(FirewallRuleDialog)))
.returns(() => mockFirewallRuleDialog.object);
connectionProfile = {
connectionName: 'new name',
serverName: 'new server',
databaseName: 'database',
userName: 'user',
password: 'password',
authenticationType: '',
savePassword: true,
groupFullName: 'g2/g2-2',
groupId: 'group id',
getOptionsKey: () => '',
matches: () => false,
providerName: mssqlProviderName,
options: {},
saveProfile: true,
id: ''
};
});
test('Add Account Failure - Error Message Shown', () => {
// ... Create a mock instance of the error message service
let errorMessageServiceStub = new TestErrorMessageService();
let mockErrorMessageService = TypeMoq.Mock.ofInstance(errorMessageServiceStub);
mockErrorMessageService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()));
// ... Create instance of the controller with an opened dialog
let controller = new FirewallRuleDialogController(instantiationService.object, undefined!, undefined!, mockErrorMessageService.object);
controller.openFirewallRuleDialog(connectionProfile, IPAddress, 'resourceID');
// If: The firewall rule dialog reports a failure
mockOnAddAccountErrorEvent.fire('Error message');
// Then: An error dialog should have been opened
mockErrorMessageService.verify(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
});
test('create firewall rule success', async () => {
let deferredPromise = new Deferred();
mockFirewallRuleDialog.setup(x => x.onServiceComplete())
.callback(() => {
deferredPromise.resolve(true);
});
// ... Create a mock instance of the account management test service
let mockAccountManagementService = getMockAccountManagementService(true);
// ... Create a mock instance of the resource provider
let mockResourceProvider = getMockResourceProvider(true, { result: true, errorMessage: '' });
// ... Create instance of the controller with an opened dialog
let controller = new FirewallRuleDialogController(instantiationService.object, mockResourceProvider.object, mockAccountManagementService.object, undefined!);
controller.openFirewallRuleDialog(connectionProfile, IPAddress, 'resourceID');
// If: The firewall rule dialog's create firewall rule get fired
mockOnCreateFirewallRule.fire();
// Then: it should get security token from account management service and call create firewall rule in resource provider
await deferredPromise;
mockAccountManagementService.verify(x => x.getSecurityToken(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
mockResourceProvider.verify(x => x.createFirewallRule(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
mockFirewallRuleDialog.verify(x => x.close(), TypeMoq.Times.once());
mockFirewallRuleDialog.verify(x => x.onServiceComplete(), TypeMoq.Times.once());
});
test('create firewall rule fails during getSecurity', async () => {
let deferredPromise = new Deferred<{}>();
// ... Create a mock instance of the error message service
let mockErrorMessageService = getMockErrorMessageService(deferredPromise);
// ... Create a mock instance of the account management test service
let mockAccountManagementService = getMockAccountManagementService(false);
// ... Create a mock instance of the resource provider
let mockResourceProvider = getMockResourceProvider(true, { result: true, errorMessage: '' });
// ... Create instance of the controller with an opened dialog
let controller = new FirewallRuleDialogController(instantiationService.object, mockResourceProvider.object, mockAccountManagementService.object, mockErrorMessageService.object);
controller.openFirewallRuleDialog(connectionProfile, IPAddress, 'resourceID');
// If: The firewall rule dialog's create firewall rule get fired
mockOnCreateFirewallRule.fire();
// Then: it should get security token from account management service and an error dialog should have been opened
await deferredPromise;
mockAccountManagementService.verify(x => x.getSecurityToken(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
mockErrorMessageService.verify(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
mockResourceProvider.verify(x => x.createFirewallRule(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.never());
});
test('create firewall rule fails during createFirewallRule in ResourceProvider - result is false', async () => {
let deferredPromise = new Deferred<{}>();
// ... Create a mock instance of the error message service
let mockErrorMessageService = getMockErrorMessageService(deferredPromise);
// ... Create a mock instance of the account management test service
let mockAccountManagementService = getMockAccountManagementService(true);
// ... Create a mock instance of the resource provider
let mockResourceProvider = getMockResourceProvider(true, { result: false, errorMessage: '' });
// ... Create instance of the controller with an opened dialog
let controller = new FirewallRuleDialogController(instantiationService.object, mockResourceProvider.object, mockAccountManagementService.object, mockErrorMessageService.object);
controller.openFirewallRuleDialog(connectionProfile, IPAddress, 'resourceID');
// If: The firewall rule dialog's create firewall rule get fired
mockOnCreateFirewallRule.fire();
// Then: it should get security token from account management service and an error dialog should have been opened
await deferredPromise;
mockAccountManagementService.verify(x => x.getSecurityToken(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
mockResourceProvider.verify(x => x.createFirewallRule(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
mockErrorMessageService.verify(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
});
test('create firewall rule fails during createFirewallRule in ResourceProvider - reject promise', async () => {
let deferredPromise = new Deferred<{}>();
// ... Create a mock instance of the error message service
let mockErrorMessageService = getMockErrorMessageService(deferredPromise);
// ... Create a mock instance of the account management test service
let mockAccountManagementService = getMockAccountManagementService(true);
// ... Create a mock instance of the resource provider
let mockResourceProvider = getMockResourceProvider(false);
// ... Create instance of the controller with an opened dialog
let controller = new FirewallRuleDialogController(instantiationService.object, mockResourceProvider.object, mockAccountManagementService.object, mockErrorMessageService.object);
controller.openFirewallRuleDialog(connectionProfile, IPAddress, 'resourceID');
// If: The firewall rule dialog's create firewall rule get fired
mockOnCreateFirewallRule.fire();
// Then: it should get security token from account management service and an error dialog should have been opened
await deferredPromise;
mockAccountManagementService.verify(x => x.getSecurityToken(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
mockResourceProvider.verify(x => x.createFirewallRule(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
mockErrorMessageService.verify(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.once());
});
});
function getMockAccountManagementService(resolveSecurityToken: boolean): TypeMoq.Mock<TestAccountManagementService> {
let accountManagementTestService = new TestAccountManagementService();
let mockAccountManagementService = TypeMoq.Mock.ofInstance(accountManagementTestService);
mockAccountManagementService.setup(x => x.getSecurityToken(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
.returns(() => resolveSecurityToken ? Promise.resolve({}) : Promise.reject(null));
return mockAccountManagementService;
}
function getMockResourceProvider(resolveCreateFirewallRule: boolean, response?: azdata.CreateFirewallRuleResponse): TypeMoq.Mock<TestResourceProvider> {
let resourceProviderStub = new TestResourceProvider();
let mockResourceProvider = TypeMoq.Mock.ofInstance(resourceProviderStub);
mockResourceProvider.setup(x => x.createFirewallRule(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()))
.returns(() => resolveCreateFirewallRule ? Promise.resolve(response) : Promise.reject(null));
return mockResourceProvider;
}
function getMockErrorMessageService(deferredPromise: Deferred<{}>): TypeMoq.Mock<TestErrorMessageService> {
let errorMessageServiceStub = new TestErrorMessageService();
let mockErrorMessageService = TypeMoq.Mock.ofInstance(errorMessageServiceStub);
mockErrorMessageService.setup(x => x.showDialog(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).callback(() => {
deferredPromise.resolve(true);
});
return mockErrorMessageService;
}

View File

@@ -11,11 +11,11 @@ import { APP_BASE_HREF, CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { providerIterator } from 'sql/platform/bootstrap/browser/bootstrapService';
import { providerIterator } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { BackupComponent } from 'sql/workbench/parts/backup/browser/backup.component';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IBootstrapParams, ISelector } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IBootstrapParams, ISelector } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
// Backup wizard main angular module
export const BackupModule = (params: IBootstrapParams, selector: string, instantiationService: IInstantiationService): Type<any> => {

View File

@@ -14,7 +14,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { bootstrapAngular } from 'sql/platform/bootstrap/browser/bootstrapService';
import { bootstrapAngular } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { append, $ } from 'vs/base/browser/dom';
import { ILogService } from 'vs/platform/log/common/log';

View File

@@ -19,7 +19,7 @@ import { TestConnectionManagementService } from 'sql/platform/connection/test/co
import { ICommandService } from 'vs/platform/commands/common/commands';
import { TestCommandService } from 'vs/editor/test/browser/editorTestServices';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { assertThrowsAsync } from 'sqltest/utils/testUtils';
import { assertThrowsAsync } from 'sql/base/test/common/async';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TestEditorService, TestDialogService } from 'vs/workbench/test/workbenchTestServices';
import { QueryInput, QueryEditorState } from 'sql/workbench/parts/query/common/queryInput';

View File

@@ -10,15 +10,8 @@ import { localize } from 'vs/nls';
import { Event, Emitter } from 'vs/base/common/event';
import { deepClone } from 'vs/base/common/objects';
import * as azdata from 'azdata';
import * as resources from 'vs/base/common/resources';
export interface ConnectionProviderProperties {
providerId: string;
displayName: string;
connectionOptions: azdata.ConnectionOption[];
}
import { ConnectionProviderProperties } from 'sql/platform/capabilities/common/capabilitiesService';
export const Extensions = {
ConnectionProviderContributions: 'connection.providers'

View File

@@ -7,7 +7,7 @@ import 'vs/css!./dashboardGridContainer';
import { Component, Inject, Input, forwardRef, ElementRef, ViewChildren, QueryList, OnDestroy, ChangeDetectorRef, ContentChild } from '@angular/core';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { TabConfig, WidgetConfig } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { DashboardWidgetWrapper } from 'sql/workbench/parts/dashboard/browser/contents/dashboardWidgetWrapper.component';
import { DashboardTab } from 'sql/workbench/parts/dashboard/browser/core/interfaces';

View File

@@ -10,8 +10,8 @@ import { Component, forwardRef, Input, ChangeDetectorRef, Inject, ViewChild, Con
import { DashboardWidgetContainer } from 'sql/workbench/parts/dashboard/browser/containers/dashboardWidgetContainer.component';
import { WidgetConfig } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { DashboardServiceInterface } from 'sql/workbench/parts/dashboard/browser/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { AngularEventType, IAngularEventingService } from 'sql/platform/angularEventing/common/angularEventingService';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { AngularEventType, IAngularEventingService } from 'sql/platform/angularEventing/browser/angularEventingService';
import { DashboardWidgetWrapper } from 'sql/workbench/parts/dashboard/browser/contents/dashboardWidgetWrapper.component';
import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';

View File

@@ -7,7 +7,7 @@ import 'vs/css!./dashboardNavSection';
import { Component, Inject, Input, forwardRef, ViewChild, ElementRef, ViewChildren, QueryList, OnDestroy, ChangeDetectorRef, OnChanges, AfterContentInit } from '@angular/core';
import { CommonServiceInterface, SingleConnectionManagementService } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface, SingleConnectionManagementService } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { WidgetConfig, TabConfig, NavSectionConfig } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { PanelComponent, IPanelOptions, NavigationBarLayout } from 'sql/base/browser/ui/panel/panel.component';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';

View File

@@ -9,7 +9,7 @@ import { Component, forwardRef, Input, OnInit, Inject, ChangeDetectorRef, Elemen
import { Event, Emitter } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import * as azdata from 'azdata';
import { memoize } from 'vs/base/common/decorators';

View File

@@ -24,7 +24,7 @@ import { TasksWidget } from 'sql/workbench/parts/dashboard/browser/widgets/tasks
import { InsightsWidget } from 'sql/workbench/parts/dashboard/browser/widgets/insights/insightsWidget.component';
import { WebviewWidget } from 'sql/workbench/parts/dashboard/browser/widgets/webview/webviewWidget.component';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import * as colors from 'vs/platform/theme/common/colorRegistry';

View File

@@ -12,7 +12,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
import { memoize } from 'vs/base/common/decorators';
import { DashboardServiceInterface } from 'sql/workbench/parts/dashboard/browser/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { IDashboardWebview, IDashboardViewService } from 'sql/platform/dashboard/browser/dashboardViewService';
import { AngularDisposable } from 'sql/base/browser/lifecycle';

View File

@@ -9,7 +9,7 @@ import { Component, Inject, Input, forwardRef, ViewChild, ViewChildren, QueryLis
import { NgGridConfig, NgGrid, NgGridItem } from 'angular2-grid';
import { DashboardServiceInterface } from 'sql/workbench/parts/dashboard/browser/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { WidgetConfig } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { DashboardWidgetWrapper } from 'sql/workbench/parts/dashboard/browser/contents/dashboardWidgetWrapper.component';
import { subscriptionToDisposable, AngularDisposable } from 'sql/base/browser/lifecycle';

View File

@@ -8,9 +8,9 @@ import * as nls from 'vs/nls';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IAngularEventingService, AngularEventType, IAngularEvent } from 'sql/platform/angularEventing/common/angularEventingService';
import { IAngularEventingService, AngularEventType, IAngularEvent } from 'sql/platform/angularEventing/browser/angularEventingService';
import { INewDashboardTabDialogService } from 'sql/workbench/services/dashboard/browser/newDashboardTabDialog';
import { IDashboardTab } from 'sql/platform/dashboard/browser/dashboardRegistry';
import { IDashboardTab } from 'sql/workbench/parts/dashboard/browser/dashboardRegistry';
import { subscriptionToDisposable } from 'sql/base/browser/lifecycle';
export class EditDashboardAction extends Action {

View File

@@ -20,7 +20,7 @@ import { MODELVIEW_CONTAINER } from 'sql/workbench/parts/dashboard/browser/conta
import { CONTROLHOST_CONTAINER } from 'sql/workbench/parts/dashboard/browser/containers/dashboardControlHostContainer.contribution';
import { NAV_SECTION } from 'sql/workbench/parts/dashboard/browser/containers/dashboardNavSection.contribution';
import { IDashboardContainerRegistry, Extensions as DashboardContainerExtensions } from 'sql/platform/dashboard/common/dashboardContainerRegistry';
import { SingleConnectionManagementService } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { SingleConnectionManagementService } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import * as Constants from 'sql/platform/connection/common/constants';
import { ILogService } from 'vs/platform/log/common/log';

View File

@@ -9,14 +9,14 @@ import 'sql/workbench/parts/dashboard/browser/core/dashboardPanelStyles';
import { Component, Inject, forwardRef, ViewChild, ElementRef, ViewChildren, QueryList, ChangeDetectorRef } from '@angular/core';
import { DashboardServiceInterface } from 'sql/workbench/parts/dashboard/browser/services/dashboardServiceInterface.service';
import { CommonServiceInterface, SingleConnectionManagementService } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface, SingleConnectionManagementService } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { WidgetConfig, TabConfig, TabSettingConfig } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { IPropertiesConfig } from 'sql/workbench/parts/dashboard/browser/pages/serverDashboardPage.contribution';
import { PanelComponent } from 'sql/base/browser/ui/panel/panel.component';
import { IDashboardRegistry, Extensions as DashboardExtensions, IDashboardTab } from 'sql/platform/dashboard/browser/dashboardRegistry';
import { IDashboardRegistry, Extensions as DashboardExtensions, IDashboardTab } from 'sql/workbench/parts/dashboard/browser/dashboardRegistry';
import { PinUnpinTabAction, AddFeatureTabAction } from './actions';
import { TabComponent, TabChild } from 'sql/base/browser/ui/panel/tab.component';
import { AngularEventType, IAngularEventingService } from 'sql/platform/angularEventing/common/angularEventingService';
import { AngularEventType, IAngularEventingService } from 'sql/platform/angularEventing/browser/angularEventingService';
import { DashboardTab, IConfigModifierCollection } from 'sql/workbench/parts/dashboard/browser/core/interfaces';
import * as dashboardHelper from 'sql/workbench/parts/dashboard/browser/core/dashboardHelper';
import { WIDGETS_CONTAINER } from 'sql/workbench/parts/dashboard/browser/containers/dashboardWidgetContainer.contribution';

View File

@@ -9,7 +9,7 @@ import { localize } from 'vs/nls';
import * as types from 'vs/base/common/types';
import * as Constants from 'sql/platform/connection/common/constants';
import { registerTab } from 'sql/platform/dashboard/browser/dashboardRegistry';
import { registerTab } from 'sql/workbench/parts/dashboard/browser/dashboardRegistry';
import { generateContainerTypeSchemaProperties } from 'sql/platform/dashboard/common/dashboardContainerRegistry';
import { NAV_SECTION, validateNavSectionContributionAndRegisterIcon } from 'sql/workbench/parts/dashboard/browser/containers/dashboardNavSection.contribution';
import { WIDGETS_CONTAINER, validateWidgetContainerContribution } from 'sql/workbench/parts/dashboard/browser/containers/dashboardWidgetContainer.contribution';

View File

@@ -7,7 +7,7 @@ import { InjectionToken, OnDestroy } from '@angular/core';
import { NgGridItemConfig } from 'angular2-grid';
import { Action } from 'vs/base/common/actions';
import { Disposable } from 'vs/base/common/lifecycle';
import { IDashboardTab } from 'sql/platform/dashboard/browser/dashboardRegistry';
import { IDashboardTab } from 'sql/workbench/parts/dashboard/browser/dashboardRegistry';
export interface IDashboardWidget {
actions: Array<Action>;

View File

@@ -9,7 +9,7 @@ import { Event } from 'vs/base/common/event';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
import { SingleConnectionManagementService } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { SingleConnectionManagementService } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
export abstract class DashboardTab extends TabChild implements OnDestroy {
public abstract layout(): void;

View File

@@ -8,7 +8,7 @@ import 'vs/css!./dashboard';
import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import * as Utils from 'sql/platform/connection/common/utils';
import { RefreshWidgetAction, EditDashboardAction } from 'sql/workbench/parts/dashboard/browser/core/actions';

View File

@@ -14,8 +14,8 @@ import { ChartsModule } from 'ng2-charts';
import CustomUrlSerializer from 'sql/base/browser/urlSerializer';
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/browser/insightRegistry';
import { Extensions as ComponentExtensions, IComponentRegistry } from 'sql/platform/dashboard/browser/modelComponentRegistry';
import { providerIterator } from 'sql/platform/bootstrap/browser/bootstrapService';
import { IBootstrapParams, ISelector } from 'sql/platform/bootstrap/common/bootstrapParams';
import { providerIterator } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { IBootstrapParams, ISelector } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -27,7 +27,7 @@ import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
/* Services */
import { BreadcrumbService } from 'sql/workbench/parts/dashboard/browser/services/breadcrumb.service';
import { DashboardServiceInterface } from 'sql/workbench/parts/dashboard/browser/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
/* Directives */
import { ComponentHostDirective } from 'sql/workbench/parts/dashboard/browser/core/componentHost.directive';

View File

@@ -13,8 +13,8 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { DashboardInput } from './dashboardInput';
import { DashboardModule } from './dashboard.module';
import { bootstrapAngular } from 'sql/platform/bootstrap/browser/bootstrapService';
import { IDashboardComponentParams } from 'sql/platform/bootstrap/common/bootstrapParams';
import { bootstrapAngular } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { IDashboardComponentParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { DASHBOARD_SELECTOR } from 'sql/workbench/parts/dashboard/browser/dashboard.component';
import { ConnectionContextKey } from 'sql/workbench/parts/connection/common/connectionContextKey';
import { IDashboardService } from 'sql/platform/dashboard/browser/dashboardService';

View File

@@ -0,0 +1,183 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Registry } from 'vs/platform/registry/common/platform';
import { IConfigurationRegistry, Extensions as ConfigurationExtension } from 'vs/platform/configuration/common/configurationRegistry';
import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';
import * as nls from 'vs/nls';
import { IExtensionPointUser, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { ProviderProperties } from 'sql/workbench/parts/dashboard/browser/widgets/properties/propertiesWidget.component';
import { DATABASE_DASHBOARD_TABS } from 'sql/workbench/parts/dashboard/browser/pages/databaseDashboardPage.contribution';
import { SERVER_DASHBOARD_TABS } from 'sql/workbench/parts/dashboard/browser/pages/serverDashboardPage.contribution';
import { DASHBOARD_CONFIG_ID, DASHBOARD_TABS_KEY_PROPERTY } from 'sql/workbench/parts/dashboard/browser/pages/dashboardPageContribution';
export const Extensions = {
DashboardContributions: 'dashboard.contributions'
};
export interface IDashboardTab {
id: string;
title: string;
provider: string | string[];
publisher: string;
description?: string;
container?: object;
when?: string;
alwaysShow?: boolean;
isHomeTab?: boolean;
}
export interface IDashboardRegistry {
registerDashboardProvider(id: string, properties: ProviderProperties): void;
getProperties(id: string): ProviderProperties;
registerTab(tab: IDashboardTab): void;
tabs: Array<IDashboardTab>;
}
class DashboardRegistry implements IDashboardRegistry {
private _properties = new Map<string, ProviderProperties>();
private _tabs = new Array<IDashboardTab>();
private _configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtension.Configuration);
private _dashboardTabContentSchemaProperties: IJSONSchemaMap = {};
/**
* Register a dashboard widget
* @param id id of the widget
*/
public registerDashboardProvider(id: string, properties: ProviderProperties): void {
this._properties.set(id, properties);
}
public getProperties(id: string): ProviderProperties {
return this._properties.get(id);
}
public registerTab(tab: IDashboardTab): void {
this._tabs.push(tab);
let dashboardConfig = this._configurationRegistry.getConfigurations().find(c => c.id === DASHBOARD_CONFIG_ID);
if (dashboardConfig) {
let dashboardDatabaseTabProperty = (<IJSONSchema>dashboardConfig.properties[DATABASE_DASHBOARD_TABS].items).properties[DASHBOARD_TABS_KEY_PROPERTY];
dashboardDatabaseTabProperty.enum.push(tab.id);
dashboardDatabaseTabProperty.enumDescriptions.push(tab.description || '');
let dashboardServerTabProperty = (<IJSONSchema>dashboardConfig.properties[SERVER_DASHBOARD_TABS].items).properties[DASHBOARD_TABS_KEY_PROPERTY];
dashboardServerTabProperty.enum.push(tab.id);
dashboardServerTabProperty.enumDescriptions.push(tab.description || '');
this._configurationRegistry.notifyConfigurationSchemaUpdated(dashboardConfig);
}
}
public get tabs(): Array<IDashboardTab> {
return this._tabs;
}
}
const dashboardRegistry = new DashboardRegistry();
Registry.add(Extensions.DashboardContributions, dashboardRegistry);
export function registerTab(tab: IDashboardTab): void {
dashboardRegistry.registerTab(tab);
}
const dashboardPropertiesPropertyContrib: IJSONSchema = {
description: nls.localize('dashboard.properties.property', "Defines a property to show on the dashboard"),
type: 'object',
properties: {
displayName: {
description: nls.localize('dashboard.properties.property.displayName', "What value to use as a label for the property"),
type: 'string'
},
value: {
description: nls.localize('dashboard.properties.property.value', "What value in the object to access for the value"),
type: 'string'
},
ignore: {
description: nls.localize('dashboard.properties.property.ignore', "Specify values to be ignored"),
type: 'array',
items: { type: 'string' }
},
default: {
description: nls.localize('dashboard.properties.property.default', "Default value to show if ignored or no value"),
type: 'string'
}
}
};
const dashboardPropertyFlavorContrib: IJSONSchema = {
description: nls.localize('dashboard.properties.flavor', "A flavor for defining dashboard properties"),
type: 'object',
properties: {
id: {
description: nls.localize('dashboard.properties.flavor.id', "Id of the flavor"),
type: 'string'
},
condition: {
description: nls.localize('dashboard.properties.flavor.condition', "Condition to use this flavor"),
type: 'object',
properties: {
field: {
description: nls.localize('dashboard.properties.flavor.condition.field', "Field to compare to"),
type: 'string'
},
operator: {
description: nls.localize('dashboard.properties.flavor.condition.operator', "Which operator to use for comparison"),
type: 'string',
enum: ['==', '<=', '>=', '!=']
},
value: {
description: nls.localize('dashboard.properties.flavor.condition.value', "Value to compare the field to"),
type: ['string', 'boolean']
}
}
},
databaseProperties: {
description: nls.localize('dashboard.properties.databaseProperties', "Properties to show for database page"),
type: 'array',
items: dashboardPropertiesPropertyContrib
},
serverProperties: {
description: nls.localize('dashboard.properties.serverProperties', "Properties to show for server page"),
type: 'array',
items: dashboardPropertiesPropertyContrib
}
}
};
const dashboardContrib: IJSONSchema = {
description: nls.localize('carbon.extension.dashboard', "Defines that this provider supports the dashboard"),
type: 'object',
properties: {
provider: {
description: nls.localize('dashboard.id', "Provider id (ex. MSSQL)"),
type: 'string'
},
flavors: {
description: nls.localize('dashboard.properties', "Property values to show on dashboard"),
type: 'array',
items: dashboardPropertyFlavorContrib
}
}
};
ExtensionsRegistry.registerExtensionPoint<ProviderProperties | ProviderProperties[]>({ extensionPoint: 'dashboard', jsonSchema: dashboardContrib }).setHandler(extensions => {
function handleCommand(contrib: ProviderProperties, extension: IExtensionPointUser<any>) {
dashboardRegistry.registerDashboardProvider(contrib.provider, contrib);
}
for (let extension of extensions) {
const { value } = extension;
if (Array.isArray<ProviderProperties>(value)) {
for (let command of value) {
handleCommand(command, extension);
}
} else {
handleCommand(value, extension);
}
}
});

View File

@@ -10,8 +10,8 @@ import { BreadcrumbClass } from 'sql/workbench/parts/dashboard/browser/services/
import { IBreadcrumbService } from 'sql/base/browser/ui/breadcrumb/interfaces';
import { DashboardServiceInterface } from 'sql/workbench/parts/dashboard/browser/services/dashboardServiceInterface.service';
import { WidgetConfig } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { IAngularEventingService } from 'sql/platform/angularEventing/common/angularEventingService';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { IAngularEventingService } from 'sql/platform/angularEventing/browser/angularEventingService';
import * as colors from 'vs/platform/theme/common/colorRegistry';
import * as nls from 'vs/nls';

View File

@@ -10,8 +10,8 @@ import { BreadcrumbClass } from 'sql/workbench/parts/dashboard/browser/services/
import { IBreadcrumbService } from 'sql/base/browser/ui/breadcrumb/interfaces';
import { WidgetConfig } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { DashboardServiceInterface } from 'sql/workbench/parts/dashboard/browser/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { IAngularEventingService } from 'sql/platform/angularEventing/common/angularEventingService';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { IAngularEventingService } from 'sql/platform/angularEventing/browser/angularEventingService';
import * as colors from 'vs/platform/theme/common/colorRegistry';
import * as nls from 'vs/nls';

View File

@@ -7,7 +7,7 @@ import { Injectable, forwardRef, Inject } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { DashboardServiceInterface } from './dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { MenuItem, IBreadcrumbService } from 'sql/base/browser/ui/breadcrumb/interfaces';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';

View File

@@ -8,15 +8,15 @@ import { Injectable, Inject, forwardRef } from '@angular/core';
import { Router } from '@angular/router';
/* SQL imports */
import { IDashboardComponentParams, IBootstrapParams } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IDashboardComponentParams, IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { IMetadataService } from 'sql/platform/metadata/common/metadataService';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { IAdminService } from 'sql/workbench/services/admin/common/adminService';
import { IQueryManagementService } from 'sql/platform/query/common/queryManagement';
import { AngularEventType, IAngularEvent, IAngularEventingService } from 'sql/platform/angularEventing/common/angularEventingService';
import { IDashboardTab } from 'sql/platform/dashboard/browser/dashboardRegistry';
import { AngularEventType, IAngularEvent, IAngularEventingService } from 'sql/platform/angularEventing/browser/angularEventingService';
import { IDashboardTab } from 'sql/workbench/parts/dashboard/browser/dashboardRegistry';
import { TabSettingConfig } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
/* VS imports */
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';

View File

@@ -7,7 +7,7 @@ import { Router } from '@angular/router';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { MetadataType } from 'sql/platform/connection/common/connectionManagement';
import { SingleConnectionManagementService, CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { SingleConnectionManagementService, CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { ManageActionContext, BaseActionContext } from 'sql/workbench/browser/actions';
import * as tree from 'vs/base/parts/tree/browser/tree';

View File

@@ -5,7 +5,7 @@
import { ManageAction, ManageActionContext } from 'sql/workbench/browser/actions';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { IAngularEventingService } from 'sql/platform/angularEventing/common/angularEventingService';
import { IAngularEventingService } from 'sql/platform/angularEventing/browser/angularEventingService';
import { ExecuteCommandAction } from 'vs/platform/actions/common/actions';
export class ExplorerManageAction extends ManageAction {

View File

@@ -11,7 +11,7 @@ import { Component, Inject, forwardRef, OnInit, ViewChild, ElementRef } from '@a
import { Router } from '@angular/router';
import { DashboardWidget, IDashboardWidget, WidgetConfig, WIDGET_CONFIG } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { ExplorerFilter, ExplorerRenderer, ExplorerDataSource, ExplorerController, ExplorerModel } from './explorerTree';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';

View File

@@ -10,7 +10,7 @@ import {
import { Observable } from 'rxjs/Observable';
import { DashboardWidget, IDashboardWidget, WIDGET_CONFIG, WidgetConfig } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { ComponentHostDirective } from 'sql/workbench/parts/dashboard/browser/core/componentHost.directive';
import { InsightAction, InsightActionContext } from 'sql/workbench/browser/actions';
import { Extensions, IInsightRegistry, IInsightsConfig, IInsightsView, getWidgetAutoRefreshState } from 'sql/platform/dashboard/browser/insightRegistry';

View File

@@ -6,9 +6,9 @@
import { Component, Inject, forwardRef, ChangeDetectorRef, OnInit, ElementRef, ViewChild } from '@angular/core';
import { DashboardWidget, IDashboardWidget, WidgetConfig, WIDGET_CONFIG } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { ConnectionManagementInfo } from 'sql/platform/connection/common/connectionManagementInfo';
import { IDashboardRegistry, Extensions as DashboardExtensions } from 'sql/platform/dashboard/browser/dashboardRegistry';
import { IDashboardRegistry, Extensions as DashboardExtensions } from 'sql/workbench/parts/dashboard/browser/dashboardRegistry';
import { DatabaseInfo, ServerInfo } from 'azdata';

View File

@@ -11,7 +11,7 @@ import { Component, Inject, forwardRef, ViewChild, OnInit, ElementRef } from '@a
/* SQL imports */
import { DashboardWidget, IDashboardWidget, WidgetConfig, WIDGET_CONFIG } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
/* VS imports */

View File

@@ -11,7 +11,7 @@ import { memoize } from 'vs/base/common/decorators';
import { DashboardWidget, IDashboardWidget, WidgetConfig, WIDGET_CONFIG } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { DashboardServiceInterface } from 'sql/workbench/parts/dashboard/browser/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { IDashboardWebview, IDashboardViewService } from 'sql/platform/dashboard/browser/dashboardViewService';
import * as azdata from 'azdata';

View File

@@ -9,7 +9,7 @@ import 'rxjs/add/observable/of';
import { WidgetConfig } from 'sql/workbench/parts/dashboard/browser/core/dashboardWidget';
import { DashboardServiceInterface } from 'sql/workbench/parts/dashboard/browser/services/dashboardServiceInterface.service';
import { SingleAdminService, SingleConnectionManagementService } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { SingleAdminService, SingleConnectionManagementService } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { PropertiesWidgetComponent } from 'sql/workbench/parts/dashboard/browser/widgets/properties/propertiesWidget.component';
import { ConnectionManagementInfo } from 'sql/platform/connection/common/connectionManagementInfo';

View File

@@ -10,7 +10,7 @@ import { VirtualizedCollection } from 'angular2-slickgrid';
import { IGridDataSet } from 'sql/workbench/parts/grid/common/interfaces';
import * as Services from 'sql/base/browser/ui/table/formatters';
import { IEditDataComponentParams, IBootstrapParams } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IEditDataComponentParams, IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { GridParentComponent } from 'sql/workbench/parts/editData/browser/gridParentComponent';
import { EditDataGridActionProvider } from 'sql/workbench/parts/editData/browser/editDataGridActions';
import { IQueryEditorService } from 'sql/workbench/services/queryEditor/common/queryEditorService';

View File

@@ -10,10 +10,10 @@ import { BrowserModule } from '@angular/platform-browser';
import { SlickGrid } from 'angular2-slickgrid';
import { EditDataComponent } from 'sql/workbench/parts/editData/browser/editData.component';
import { providerIterator } from 'sql/platform/bootstrap/browser/bootstrapService';
import { providerIterator } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IBootstrapParams, ISelector } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IBootstrapParams, ISelector } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
export const EditDataModule = (params: IBootstrapParams, selector: string, instantiationService: IInstantiationService): Type<any> => {

View File

@@ -15,9 +15,9 @@ import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import * as types from 'vs/base/common/types';
import { IQueryModelService } from 'sql/platform/query/common/queryModel';
import { bootstrapAngular } from 'sql/platform/bootstrap/browser/bootstrapService';
import { bootstrapAngular } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { BareResultsGridInfo } from 'sql/workbench/parts/query/browser/queryResultsEditor';
import { IEditDataComponentParams } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IEditDataComponentParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { EditDataModule } from 'sql/workbench/parts/editData/browser/editData.module';
import { EDITDATA_SELECTOR } from 'sql/workbench/parts/editData/browser/editData.component';
import { EditDataResultsInput } from 'sql/workbench/parts/editData/browser/editDataResultsInput';

View File

@@ -15,7 +15,7 @@ import { AgentViewComponent } from 'sql/workbench/parts/jobManagement/browser/ag
import { IJobManagementService } from 'sql/platform/jobManagement/common/interfaces';
import { EditAlertAction, DeleteAlertAction, NewAlertAction } from 'sql/platform/jobManagement/browser/jobActions';
import { JobManagementView, JobActionContext } from 'sql/workbench/parts/jobManagement/browser/jobManagementView';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IAction } from 'vs/base/common/actions';

View File

@@ -11,7 +11,7 @@ import * as dom from 'vs/base/browser/dom';
import { OnInit, Component, Inject, Input, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, ChangeDetectionStrategy, Injectable } from '@angular/core';
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
import { AgentViewComponent } from 'sql/workbench/parts/jobManagement/browser/agentView.component';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { RunJobAction, StopJobAction, EditJobAction, JobsRefreshAction } from 'sql/platform/jobManagement/browser/jobActions';
import { JobCacheObject } from 'sql/platform/jobManagement/common/jobManagementService';
import { JobManagementUtilities } from 'sql/platform/jobManagement/browser/jobManagementUtilities';

View File

@@ -7,7 +7,7 @@ import * as azdata from 'azdata';
import { ElementRef, AfterContentChecked, ViewChild } from '@angular/core';
import { Table } from 'sql/base/browser/ui/table/table';
import { AgentViewComponent } from 'sql/workbench/parts/jobManagement/browser/agentView.component';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { IAction, Action } from 'vs/base/common/actions';
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';

View File

@@ -11,7 +11,7 @@ import { attachListStyler } from 'vs/platform/theme/common/styler';
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import {
JobStepsViewController, JobStepsViewDataSource, JobStepsViewFilter,
JobStepsViewRenderer, JobStepsViewModel

View File

@@ -19,7 +19,7 @@ import { JobManagementUtilities } from 'sql/platform/jobManagement/browser/jobMa
import { HeaderFilter } from 'sql/base/browser/ui/table/plugins/headerFilter.plugin';
import { IJobManagementService } from 'sql/platform/jobManagement/common/interfaces';
import { JobManagementView, JobActionContext } from 'sql/workbench/parts/jobManagement/browser/jobManagementView';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';

View File

@@ -11,7 +11,7 @@ import * as dom from 'vs/base/browser/dom';
import { OnInit, Component, Inject, Input, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, ChangeDetectionStrategy, Injectable, PipeTransform, Pipe } from '@angular/core';
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
import { AgentViewComponent } from 'sql/workbench/parts/jobManagement/browser/agentView.component';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { RunJobAction, StopJobAction, JobsRefreshAction, EditNotebookJobAction, EditJobAction, OpenMaterializedNotebookAction, OpenTemplateNotebookAction, RenameNotebookMaterializedAction, PinNotebookMaterializedAction, UnpinNotebookMaterializedAction, DeleteMaterializedNotebookAction } from 'sql/platform/jobManagement/browser/jobActions';
import { NotebookCacheObject } from 'sql/platform/jobManagement/common/jobManagementService';
import { JobManagementUtilities } from 'sql/platform/jobManagement/browser/jobManagementUtilities';

View File

@@ -19,7 +19,7 @@ import { JobManagementUtilities } from 'sql/platform/jobManagement/browser/jobMa
import { HeaderFilter } from 'sql/base/browser/ui/table/plugins/headerFilter.plugin';
import { IJobManagementService } from 'sql/platform/jobManagement/common/interfaces';
import { JobManagementView, JobActionContext } from 'sql/workbench/parts/jobManagement/browser/jobManagementView';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';

View File

@@ -14,7 +14,7 @@ import { AgentViewComponent } from 'sql/workbench/parts/jobManagement/browser/ag
import { IJobManagementService } from 'sql/platform/jobManagement/common/interfaces';
import { EditOperatorAction, DeleteOperatorAction, NewOperatorAction } from 'sql/platform/jobManagement/browser/jobActions';
import { JobManagementView } from 'sql/workbench/parts/jobManagement/browser/jobManagementView';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';

View File

@@ -13,7 +13,7 @@ import { Table } from 'sql/base/browser/ui/table/table';
import { AgentViewComponent } from 'sql/workbench/parts/jobManagement/browser/agentView.component';
import { IJobManagementService } from 'sql/platform/jobManagement/common/interfaces';
import { EditProxyAction, DeleteProxyAction, NewProxyAction } from 'sql/platform/jobManagement/browser/jobActions';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
import { JobManagementView } from 'sql/workbench/parts/jobManagement/browser/jobManagementView';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';

View File

@@ -27,7 +27,7 @@ import { ICellModel } from 'sql/workbench/parts/notebook/browser/models/modelInt
import { NotebookModel } from 'sql/workbench/parts/notebook/browser/models/notebookModel';
import { ISanitizer, defaultSanitizer } from 'sql/workbench/parts/notebook/browser/outputs/sanitizer';
import { CellToggleMoreActions } from 'sql/workbench/parts/notebook/browser/cellToggleMoreActions';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { useInProcMarkdown, convertVscodeResourceToFileInSubDirectories } from 'sql/workbench/parts/notebook/browser/models/notebookUtils';
export const TEXT_SELECTOR: string = 'text-cell-component';

View File

@@ -52,7 +52,7 @@ import { LabeledMenuItemActionItem, fillInActions } from 'vs/platform/actions/br
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Button } from 'sql/base/browser/ui/button/button';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { IBootstrapParams } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { getErrorMessage } from 'vs/base/common/errors';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';

View File

@@ -9,8 +9,8 @@ import { CommonModule, APP_BASE_HREF } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { ComponentHostDirective } from 'sql/workbench/parts/dashboard/browser/core/componentHost.directive';
import { providerIterator } from 'sql/platform/bootstrap/browser/bootstrapService';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { providerIterator } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { EditableDropDown } from 'sql/platform/browser/editableDropdown/editableDropdown.component';
import { NotebookComponent } from 'sql/workbench/parts/notebook/browser/notebook.component';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -27,7 +27,7 @@ import { InputBox } from 'sql/platform/browser/inputbox/inputBox.component';
import { IMimeComponentRegistry, Extensions } from 'sql/workbench/parts/notebook/browser/outputs/mimeRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { LinkHandlerDirective } from 'sql/workbench/parts/notebook/browser/cellViews/linkHandler.directive';
import { IBootstrapParams, ISelector } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IBootstrapParams, ISelector } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { ICellComponenetRegistry, Extensions as OutputComponentExtensions } from 'sql/platform/notebooks/common/outputRegistry';
import { CollapseComponent } from 'sql/workbench/parts/notebook/browser/cellViews/collapse.component';

View File

@@ -7,7 +7,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorOptions } from 'vs/workbench/common/editor';
import * as DOM from 'vs/base/browser/dom';
import { bootstrapAngular } from 'sql/platform/bootstrap/browser/bootstrapService';
import { bootstrapAngular } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { CancellationToken } from 'vs/base/common/cancellation';

View File

@@ -8,7 +8,7 @@ import * as os from 'os';
import * as assert from 'assert';
import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService';
import { ConnectionManagementService } from 'sql/platform/connection/browser/connectionManagementService';
import { ConnectionManagementService } from 'sql/workbench/services/connection/browser/connectionManagementService';
import { CellModel } from 'sql/workbench/parts/notebook/browser/models/cell';
import { CellTypes, NotebookChangeType } from 'sql/workbench/parts/notebook/common/models/contracts';
import { ModelFactory } from 'sql/workbench/parts/notebook/browser/models/modelFactory';

View File

@@ -9,7 +9,7 @@ import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import * as tempWrite from 'temp-write';
import { LocalContentManager } from 'sql/workbench/services/notebook/common/localContentManager';
import * as testUtils from '../../../../../../sqltest/utils/testUtils';
import * as testUtils from '../../../../../base/test/common/async';
import { CellTypes } from 'sql/workbench/parts/notebook/common/models/contracts';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { TestFileService } from 'vs/workbench/test/workbenchTestServices';

View File

@@ -5,7 +5,7 @@
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { ServerTreeView } from 'sql/workbench/parts/objectExplorer/browser/serverTreeView';
import { ConnectionManagementService } from 'sql/platform/connection/browser/connectionManagementService';
import { ConnectionManagementService } from 'sql/workbench/services/connection/browser/connectionManagementService';
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';

View File

@@ -9,13 +9,13 @@ import { forwardRef, NgModule, ComponentFactoryResolver, Inject, ApplicationRef
import { FormsModule } from '@angular/forms';
import { CommonModule, APP_BASE_HREF } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { WizardNavigation } from 'sql/platform/dialog/browser/wizardNavigation.component';
import { WizardNavigation } from 'sql/workbench/services/dialog/browser/wizardNavigation.component';
import { Extensions, IComponentRegistry } from 'sql/platform/dashboard/browser/modelComponentRegistry';
import { ModelViewContent } from 'sql/workbench/browser/modelComponents/modelViewContent.component';
import { ModelComponentWrapper } from 'sql/workbench/browser/modelComponents/modelComponentWrapper.component';
import { ComponentHostDirective } from 'sql/workbench/parts/dashboard/browser/core/componentHost.directive';
import { providerIterator } from 'sql/platform/bootstrap/browser/bootstrapService';
import { CommonServiceInterface } from 'sql/platform/bootstrap/browser/commonServiceInterface.service';
import { providerIterator } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
import { EditableDropDown } from 'sql/platform/browser/editableDropdown/editableDropdown.component';
import { QueryModelViewTabContainer } from 'sql/workbench/parts/query/browser/modelViewTab/queryModelViewTabContainer.component';
import { Checkbox } from 'sql/base/browser/ui/checkbox/checkbox.component';
@@ -24,7 +24,7 @@ import { InputBox } from 'sql/platform/browser/inputbox/inputBox.component';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Registry } from 'vs/platform/registry/common/platform';
import { IBootstrapParams, ISelector } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IBootstrapParams, ISelector } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
export const QueryModelViewTabModule = (params, selector: string, instantiationService: IInstantiationService): any => {

View File

@@ -7,7 +7,7 @@ import { Dimension } from 'vs/base/browser/dom';
import { dispose } from 'vs/base/common/lifecycle';
import { IPanelView, IPanelTab } from 'sql/base/browser/ui/panel/panel';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { bootstrapAngular } from 'sql/platform/bootstrap/browser/bootstrapService';
import { bootstrapAngular } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { QueryModelViewTabModule } from 'sql/workbench/parts/query/browser/modelViewTab/queryModelViewTab.module';
import { QueryModelViewState } from 'sql/workbench/parts/query/common/modelViewTab/modelViewState';

View File

@@ -6,10 +6,10 @@
import 'vs/css!./media/dialogModal';
import { Component, ViewChild, Inject, forwardRef, ElementRef, AfterViewInit } from '@angular/core';
import { ModelViewContent } from 'sql/workbench/browser/modelComponents/modelViewContent.component';
import { DialogPane } from 'sql/platform/dialog/browser/dialogPane';
import { DialogPane } from 'sql/workbench/services/dialog/browser/dialogPane';
import { ComponentEventType } from 'sql/workbench/browser/modelComponents/interfaces';
import { Event, Emitter } from 'vs/base/common/event';
import { IBootstrapParams } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
export interface LayoutRequestParams {
modelViewId?: string;

View File

@@ -22,7 +22,7 @@ import {
import { QueryInput } from 'sql/workbench/parts/query/common/queryInput';
import { QueryEditor } from 'sql/workbench/parts/query/browser/queryEditor';
import { QueryModelService } from 'sql/platform/query/common/queryModelService';
import { ConnectionManagementService } from 'sql/platform/connection/browser/connectionManagementService';
import { ConnectionManagementService } from 'sql/workbench/services/connection/browser/connectionManagementService';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import * as TypeMoq from 'typemoq';

View File

@@ -13,7 +13,7 @@ import { QueryResultsInput } from 'sql/workbench/parts/query/common/queryResults
import { QueryModelService } from 'sql/platform/query/common/queryModelService';
import { QueryInput } from 'sql/workbench/parts/query/common/queryInput';
import { INewConnectionParams, ConnectionType, RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement';
import { ConnectionManagementService } from 'sql/platform/connection/browser/connectionManagementService';
import { ConnectionManagementService } from 'sql/workbench/services/connection/browser/connectionManagementService';
import { RunQueryAction, ListDatabasesActionItem } from 'sql/workbench/parts/query/browser/queryActions';
import { EditorDescriptorService } from 'sql/workbench/services/queryEditor/browser/editorDescriptorService';

View File

@@ -8,7 +8,7 @@ import 'vs/css!./media/qp';
import { ElementRef, Component, Inject, forwardRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
import * as QP from 'html-query-plan';
import { IQueryPlanParams, IBootstrapParams } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IQueryPlanParams, IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { registerThemingParticipant, ICssStyleCollector, ITheme } from 'vs/platform/theme/common/themeService';

View File

@@ -7,11 +7,11 @@ import { NgModule, Inject, forwardRef, ApplicationRef, ComponentFactoryResolver,
import { APP_BASE_HREF, CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { providerIterator } from 'sql/platform/bootstrap/browser/bootstrapService';
import { providerIterator } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { QueryPlanComponent } from 'sql/workbench/parts/queryPlan/browser/queryPlan.component';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IBootstrapParams, ISelector } from 'sql/platform/bootstrap/common/bootstrapParams';
import { IBootstrapParams, ISelector } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
// Connection Dashboard main angular module
export const QueryPlanModule = (params: IBootstrapParams, selector: string, instantiationService: IInstantiationService): Type<any> => {

View File

@@ -11,8 +11,8 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { QueryPlanInput } from 'sql/workbench/parts/queryPlan/common/queryPlanInput';
import { QueryPlanModule } from 'sql/workbench/parts/queryPlan/browser/queryPlan.module';
import { bootstrapAngular } from 'sql/platform/bootstrap/browser/bootstrapService';
import { IQueryPlanParams } from 'sql/platform/bootstrap/common/bootstrapParams';
import { bootstrapAngular } from 'sql/workbench/services/bootstrap/browser/bootstrapService';
import { IQueryPlanParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { QUERYPLAN_SELECTOR } from 'sql/workbench/parts/queryPlan/browser/queryPlan.component';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IStorageService } from 'vs/platform/storage/common/storage';

View File

@@ -12,8 +12,8 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { Memento } from 'vs/workbench/common/memento';
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 { AccountDialogController } from 'sql/workbench/parts/accounts/browser/accountDialogController';
import { AutoOAuthDialogController } from 'sql/workbench/parts/accounts/browser/autoOAuthDialogController';
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accounts/common/eventTypes';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
import { Deferred } from 'sql/base/common/promise';

View File

@@ -7,14 +7,14 @@ import * as assert from 'assert';
import * as azdata from 'azdata';
import * as TypeMoq from 'typemoq';
import AccountStore from 'sql/platform/accounts/common/accountStore';
import { AccountDialogController } from 'sql/platform/accounts/browser/accountDialogController';
import { AccountDialogController } from 'sql/workbench/parts/accounts/browser/accountDialogController';
import { AccountManagementService } from 'sql/workbench/services/accountManagement/browser/accountManagementService';
import { AccountAdditionResult, AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accounts/common/eventTypes';
import { IAccountStore } from 'sql/platform/accounts/common/interfaces';
import { AccountProviderStub } from 'sql/platform/accounts/test/common/testAccountManagementService';
import { EventVerifierSingle } from 'sqltest/utils/eventVerifier';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { TestStorageService } from 'vs/workbench/test/workbenchTestServices';
import { EventVerifierSingle } from 'sql/base/test/common/event';
// SUITE CONSTANTS /////////////////////////////////////////////////////////
const hasAccountProvider: azdata.AccountProviderMetadata = {

View File

@@ -0,0 +1,70 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { NgModuleRef, PlatformRef, Provider, enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { IInstantiationService, _util } from 'vs/platform/instantiation/common/instantiation';
import { IEditorInput } from 'vs/workbench/common/editor';
import { Trace } from 'vs/platform/instantiation/common/instantiationService';
import { values } from 'vs/base/common/map';
import { IModuleFactory, IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
const selectorCounter = new Map<string, number>();
export function providerIterator(service: IInstantiationService): Provider[] {
return Array.from(values(_util.serviceIds)).map(v => {
let factory = () => {
return (<any>service)._getOrCreateServiceInstance(v, Trace.traceCreation(v));
};
factory.prototype = factory;
return {
provide: v, useFactory: factory
};
});
}
function createUniqueSelector(selector: string): string {
let num: number;
if (selectorCounter.has(selector)) {
num = selectorCounter.get(selector);
} else {
num = 0;
}
selectorCounter.set(selector, num + 1);
return `${selector}_${num}`;
}
let platform: PlatformRef;
export function bootstrapAngular<T>(service: IInstantiationService, moduleType: IModuleFactory<T>, container: HTMLElement, selectorString: string, params: IBootstrapParams, input?: IEditorInput, callbackSetModule?: (value: NgModuleRef<T>) => void): string {
// Create the uniqueSelectorString
let uniqueSelectorString = createUniqueSelector(selectorString);
let selector = document.createElement(uniqueSelectorString);
container.appendChild(selector);
if (!platform) {
service.invokeFunction((accessor) => {
const environmentService = accessor.get(IEnvironmentService);
if (environmentService.isBuilt) {
enableProdMode();
}
});
platform = platformBrowserDynamic();
}
platform.bootstrapModule(moduleType(params, uniqueSelectorString, service)).then(moduleRef => {
if (input) {
input.onDispose(() => {
moduleRef.destroy();
});
}
if (callbackSetModule) {
callbackSetModule(moduleRef);
}
});
return uniqueSelectorString;
}

View File

@@ -0,0 +1,171 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* Node Modules */
import { Injectable, Inject } from '@angular/core';
import { Observable } from 'rxjs/Observable';
/* SQL imports */
import { IDefaultComponentParams, IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
import { IMetadataService } from 'sql/platform/metadata/common/metadataService';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { ConnectionManagementInfo } from 'sql/platform/connection/common/connectionManagementInfo';
import { IAdminService } from 'sql/workbench/services/admin/common/adminService';
import { IQueryManagementService } from 'sql/platform/query/common/queryManagement';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { AngularDisposable } from 'sql/base/browser/lifecycle';
import { ConnectionContextKey } from 'sql/workbench/parts/connection/common/connectionContextKey';
import { ProviderMetadata, DatabaseInfo, SimpleExecuteResult } from 'azdata';
/* VS imports */
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
/* Wrapper for a metadata service that contains the uri string to use on each request */
export class SingleConnectionMetadataService {
constructor(
private _metadataService: IMetadataService,
private _uri: string
) { }
get metadata(): Observable<ProviderMetadata | undefined> {
return Observable.fromPromise(this._metadataService.getMetadata(this._uri));
}
get databaseNames(): Observable<string[]> {
return Observable.fromPromise(this._metadataService.getDatabaseNames(this._uri));
}
}
/* Wrapper for a connection service that contains the uri string to use on each request */
export class SingleConnectionManagementService {
constructor(
private _connectionService: IConnectionManagementService,
private _uri: string,
private _contextKey: ConnectionContextKey
) { }
public changeDatabase(name: string): Promise<boolean> {
return Promise.resolve(this._connectionService.changeDatabase(this._uri, name).then(e => {
// we need to update our context
this._contextKey.set(this.connectionInfo.connectionProfile);
return e;
}));
}
public get connectionInfo(): ConnectionManagementInfo {
return this._connectionService.getConnectionInfo(this._uri);
}
}
export class SingleAdminService {
constructor(
private _adminService: IAdminService,
private _uri: string
) { }
public get databaseInfo(): Observable<DatabaseInfo> {
return Observable.fromPromise(this._adminService.getDatabaseInfo(this._uri));
}
}
export class SingleQueryManagementService {
constructor(
private _queryManagementService: IQueryManagementService,
private _uri: string
) { }
public runQueryAndReturn(queryString: string): Thenable<SimpleExecuteResult> {
return this._queryManagementService.runQueryAndReturn(this._uri, queryString);
}
}
/*
Providers a interface between a UI interface and the rest of carbon.
Stores the uri and unique selector of a UI instance and uses that
whenever a call to a carbon service needs this information, so that the widgets
don't need to be aware of the uri or selector. Simplifies the initialization and
usage of a widget.
*/
@Injectable()
export class CommonServiceInterface extends AngularDisposable {
protected _uri: string;
/* Special Services */
protected _singleMetadataService: SingleConnectionMetadataService;
protected _singleConnectionManagementService: SingleConnectionManagementService;
protected _singleAdminService: SingleAdminService;
protected _singleQueryManagementService: SingleQueryManagementService;
public scopedContextKeyService: IContextKeyService;
protected _connectionContextKey: ConnectionContextKey;
constructor(
@Inject(IBootstrapParams) protected _params: IDefaultComponentParams,
@Inject(IMetadataService) protected _metadataService: IMetadataService,
@Inject(IConnectionManagementService) protected _connectionManagementService: IConnectionManagementService,
@Inject(IAdminService) protected _adminService: IAdminService,
@Inject(IQueryManagementService) protected _queryManagementService: IQueryManagementService
) {
super();
// during testing there may not be params
if (this._params) {
this.scopedContextKeyService = this._params.scopedContextService;
this._connectionContextKey = this._params.connectionContextKey;
this.uri = this._params.ownerUri;
}
}
public get metadataService(): SingleConnectionMetadataService {
return this._singleMetadataService;
}
public get connectionManagementService(): SingleConnectionManagementService {
return this._singleConnectionManagementService;
}
public get adminService(): SingleAdminService {
return this._singleAdminService;
}
public get queryManagementService(): SingleQueryManagementService {
return this._singleQueryManagementService;
}
protected setUri(uri: string) {
this._uri = uri;
this._singleMetadataService = new SingleConnectionMetadataService(this._metadataService, this._uri);
this._singleConnectionManagementService = new SingleConnectionManagementService(this._connectionManagementService, this._uri, this._connectionContextKey);
this._singleAdminService = new SingleAdminService(this._adminService, this._uri);
this._singleQueryManagementService = new SingleQueryManagementService(this._queryManagementService, this._uri);
}
/**
* Set the uri for this instance, should only be set once
* Inits all the services that depend on knowing a uri
*/
protected set uri(uri: string) {
this.setUri(uri);
}
protected get uri(): string {
return this._uri;
}
/**
* Gets the underlying Uri
* In general don't use this, use specific services instances exposed publicly
*/
public getUnderlyingUri(): string {
return this._uri;
}
public getOriginalConnectionProfile(): IConnectionProfile {
return this._params.connection;
}
}

View File

@@ -0,0 +1,53 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { DataService } from 'sql/workbench/parts/grid/common/dataService';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ConnectionContextKey } from 'sql/workbench/parts/connection/common/connectionContextKey';
import { Event } from 'vs/base/common/event';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
export interface IQueryComponentParams extends IBootstrapParams {
dataService: DataService;
onSaveViewState: Event<void>;
onRestoreViewState: Event<void>;
}
export interface IEditDataComponentParams extends IBootstrapParams {
dataService: DataService;
onSaveViewState: Event<void>;
onRestoreViewState: Event<void>;
}
export interface IDefaultComponentParams extends IBootstrapParams {
connection: IConnectionProfile;
ownerUri: string;
scopedContextService: IContextKeyService;
connectionContextKey: ConnectionContextKey;
}
export interface IDashboardComponentParams extends IDefaultComponentParams {
}
export interface ITaskDialogComponentParams extends IBootstrapParams {
ownerUri: string;
}
export interface IQueryPlanParams extends IBootstrapParams {
planXml: string;
}
export const ISelector = 'selector';
export const IBootstrapParams = 'bootstrap_params';
export interface IBootstrapParams {
}
export interface Type<T> {
new(...args: any[]): T;
}
export type IModuleFactory<T> = (params: IBootstrapParams, selector: string, service: IInstantiationService) => Type<T>;

Some files were not shown because too many files have changed in this diff Show More