Remove rest of builder (#4963)

* removes more builder references

* remove builder from profiler

* formatting

* fix profiler dailog

* remove builder from oatuhdialog

* remove the rest of builder references

* formatting
This commit is contained in:
Anthony Dresser
2019-04-10 13:23:33 -07:00
committed by GitHub
parent 9b053c50c2
commit a74510544f
18 changed files with 616 additions and 2226 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-builder-hidden {
display: none !important;
}
export function isHidden(element: HTMLElement): boolean {
return element.style.display === 'none';
}

View File

@@ -8,28 +8,25 @@ import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { BackupModule } from 'sql/parts/disasterRecovery/backup/backup.module';
import { BACKUP_SELECTOR } from 'sql/parts/disasterRecovery/backup/backup.component';
import { attachModalDialogStyler } from 'sql/platform/theme/common/styler';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Builder } from 'sql/base/browser/builder';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { bootstrapAngular } from 'sql/services/bootstrap/bootstrapService';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { append, $ } from 'vs/base/browser/dom';
export class BackupDialog extends Modal {
private _bodyBuilder: Builder;
private _body: HTMLElement;
private _backupTitle: string;
private _uniqueSelector: string;
private _moduleRef: any;
constructor(
@IThemeService themeService: IThemeService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@ITelemetryService telemetryService: ITelemetryService,
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService private _instantiationService: IInstantiationService,
@@ -39,9 +36,7 @@ export class BackupDialog extends Modal {
}
protected renderBody(container: HTMLElement) {
new Builder(container).div({ 'class': 'backup-dialog' }, (builder) => {
this._bodyBuilder = builder;
});
this._body = append(container, $('.backup-dialog'));
}
public render() {
@@ -49,14 +44,14 @@ export class BackupDialog extends Modal {
attachModalDialogStyler(this, this._themeService);
// Add angular component template to dialog body
this.bootstrapAngular(this._bodyBuilder.getHTMLElement());
this.bootstrapAngular(this._body);
}
/**
* Get the bootstrap params and perform the bootstrap
*/
private bootstrapAngular(bodyContainer: HTMLElement) {
this._uniqueSelector = bootstrapAngular(this._instantiationService,
bootstrapAngular(this._instantiationService,
BackupModule,
bodyContainer,
BACKUP_SELECTOR,

View File

@@ -3,9 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/restoreDialog';
import { Builder, $ } from 'sql/base/browser/builder';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Event, Emitter } from 'vs/base/common/event';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
@@ -18,6 +17,8 @@ import { localize } from 'vs/nls';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { mixin } from 'vs/base/common/objects';
import * as strings from 'vs/base/common/strings';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
import * as DOM from 'vs/base/browser/dom';
import * as azdata from 'azdata';
@@ -41,8 +42,6 @@ import { TabbedPanel, PanelTabIdentifier } from 'sql/base/browser/ui/panel/panel
import { ServiceOptionType } from 'sql/workbench/api/common/sqlExtHostTypes';
import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService';
import { IFileBrowserDialogController } from 'sql/workbench/services/fileBrowser/common/fileBrowserDialogController';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
interface FileListElement {
logicalFileName: string;
@@ -129,7 +128,7 @@ export class RestoreDialog extends Modal {
constructor(
optionsMetadata: azdata.ServiceOption[],
@IWorkbenchLayoutService layoutService: ILayoutService,
@ILayoutService layoutService: ILayoutService,
@IThemeService themeService: IThemeService,
@IContextViewService private _contextViewService: IContextViewService,
@ITelemetryService telemetryService: ITelemetryService,
@@ -137,11 +136,11 @@ export class RestoreDialog extends Modal {
@IFileBrowserDialogController private fileBrowserDialogService: IFileBrowserDialogController,
@IClipboardService clipboardService: IClipboardService,
) {
super(localize('RestoreDialogTitle', 'Restore database'), TelemetryKeys.Restore, telemetryService, layoutService, clipboardService, themeService, contextKeyService, { hasErrors: true, isWide: true, hasSpinner: true });
this._restoreTitle = localize('restoreDialog.restoreTitle', 'Restore database');
this._databaseTitle = localize('restoreDialog.database', 'Database');
this._backupFileTitle = localize('restoreDialog.backupFile', 'Backup file');
this._restoreLabel = localize('restoreDialog.restore', 'Restore');
super(localize('RestoreDialogTitle', "Restore database"), TelemetryKeys.Restore, telemetryService, layoutService, clipboardService, themeService, contextKeyService, { hasErrors: true, isWide: true, hasSpinner: true });
this._restoreTitle = localize('restoreDialog.restoreTitle', "Restore database");
this._databaseTitle = localize('restoreDialog.database', "Database");
this._backupFileTitle = localize('restoreDialog.backupFile', "Backup file");
this._restoreLabel = localize('restoreDialog.restore', "Restore");
// view model
this.viewModel = new RestoreViewModel(optionsMetadata);
@@ -169,225 +168,176 @@ export class RestoreDialog extends Modal {
}
protected renderBody(container: HTMLElement) {
const restoreFromElement = DOM.$('.restore-from');
this.createLabelElement(restoreFromElement, localize('source', "Source"), true);
this._restoreFromSelectBox = this.createSelectBoxHelper(restoreFromElement, localize('restoreFrom', "Restore from"), [this._databaseTitle, this._backupFileTitle], this._databaseTitle);
let restoreFromElement;
$().div({ class: 'restore-from' }, (restoreFromContainer) => {
restoreFromElement = restoreFromContainer.getHTMLElement();
this.createLabelElement(restoreFromContainer, localize('source', 'Source'), true);
this._restoreFromSelectBox = this.createSelectBoxHelper(restoreFromContainer, localize('restoreFrom', 'Restore from'), [this._databaseTitle, this._backupFileTitle], this._databaseTitle);
});
this._restoreFromBackupFileElement = DOM.$('.backup-file-path');
DOM.hide(this._restoreFromBackupFileElement);
const errorMessage = localize('missingBackupFilePathError', "Backup file path is required.");
const validationOptions: IInputOptions = {
validationOptions: {
validation: (value: string) => !value ? ({ type: MessageType.ERROR, content: errorMessage }) : null
},
placeholder: localize('multipleBackupFilePath', "Please enter one or more file paths separated by commas"),
ariaLabel: LocalizedStrings.BACKFILEPATH
};
const filePathInputContainer = DOM.append(this._restoreFromBackupFileElement, DOM.$('.dialog-input-section'));
DOM.append(filePathInputContainer, DOM.$('.dialog-label')).innerText = LocalizedStrings.BACKFILEPATH;
$().div({ class: 'backup-file-path' }, (filePathContainer) => {
filePathContainer.hide();
this._restoreFromBackupFileElement = filePathContainer.getHTMLElement();
let errorMessage = localize('missingBackupFilePathError', 'Backup file path is required.');
let validationOptions: IInputOptions = {
validationOptions: {
validation: (value: string) => !value ? ({ type: MessageType.ERROR, content: errorMessage }) : null
},
placeholder: localize('multipleBackupFilePath', 'Please enter one or more file paths separated by commas'),
ariaLabel: LocalizedStrings.BACKFILEPATH
};
this._filePathInputBox = new InputBox(DOM.append(filePathInputContainer, DOM.$('.dialog-input')), this._contextViewService, validationOptions);
filePathContainer.div({ class: 'dialog-input-section' }, (inputContainer) => {
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => {
labelContainer.safeInnerHtml(LocalizedStrings.BACKFILEPATH);
});
this._browseFileButton = new Button(DOM.append(filePathInputContainer, DOM.$('.file-browser')));
this._browseFileButton.label = '...';
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => {
this._filePathInputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, validationOptions);
});
inputContainer.div({ class: 'file-browser' }, (inputCellContainer) => {
this._browseFileButton = new Button(inputCellContainer.getHTMLElement());
this._browseFileButton.label = '...';
});
});
});
let sourceDatabasesElement;
$().div({ class: 'source-database-list' }, (sourceDatabasesContainer) => {
sourceDatabasesElement = sourceDatabasesContainer.getHTMLElement();
this._sourceDatabaseSelectBox = this.createSelectBoxHelper(sourceDatabasesContainer, localize('database', 'Database'), [], '');
});
const sourceDatabasesElement = DOM.$('.source-database-list');
this._sourceDatabaseSelectBox = this.createSelectBoxHelper(sourceDatabasesElement, localize('database', "Database"), [], '');
// Source section
let sourceElement: HTMLElement;
$().div({ class: 'source-section new-section' }, (sourceContainer) => {
sourceElement = sourceContainer.getHTMLElement();
sourceContainer.append(restoreFromElement);
sourceContainer.append(this._restoreFromBackupFileElement);
sourceContainer.append(sourceDatabasesElement);
});
const sourceElement = DOM.$('.source-section.new-section');
sourceElement.append(restoreFromElement);
sourceElement.append(this._restoreFromBackupFileElement);
sourceElement.append(sourceDatabasesElement);
// Destination section
let destinationElement: HTMLElement;
$().div({ class: 'destination-section new-section' }, (destinationContainer) => {
destinationElement = destinationContainer.getHTMLElement();
this.createLabelElement(destinationContainer, localize('destination', 'Destination'), true);
const destinationElement = DOM.$('.destination-section.new-section');
this.createLabelElement(destinationElement, localize('destination', "Destination"), true);
destinationContainer.div({ class: 'dialog-input-section' }, (inputContainer) => {
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => {
labelContainer.text(LocalizedStrings.TARGETDATABASE);
});
const destinationInputContainer = DOM.append(destinationElement, DOM.$('.dialog-input-section'));
DOM.append(destinationInputContainer, DOM.$('.dialog-label')).innerText = LocalizedStrings.TARGETDATABASE;
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => {
// Get the bootstrap params and perform the bootstrap
inputCellContainer.style('width', '100%');
this._databaseDropdown = new Dropdown(inputCellContainer.getHTMLElement(), this._contextViewService, this.layoutService,
{
strictSelection: false,
ariaLabel: LocalizedStrings.TARGETDATABASE,
actionLabel: localize('restoreDialog.toggleDatabaseNameDropdown', 'Select Database Toggle Dropdown')
}
);
this._databaseDropdown.onValueChange(s => {
this.databaseSelected(s);
});
const dropdownContainer = DOM.append(destinationInputContainer, DOM.$('.dialog-input'));
this._databaseDropdown.onBlur(() => {
this.databaseSelected(this._databaseDropdown.value);
});
// Get the bootstrap params and perform the bootstrap
dropdownContainer.style.width = '100%';
this._databaseDropdown.onFocus(() => {
this._onDatabaseListFocused.fire();
});
this._databaseDropdown.value = this.viewModel.targetDatabaseName;
attachEditableDropdownStyler(this._databaseDropdown, this._themeService);
});
});
this._destinationRestoreToInputBox = this.createInputBoxHelper(destinationContainer, localize('restoreTo', 'Restore to'));
this._databaseDropdown = new Dropdown(dropdownContainer, this._contextViewService, this.layoutService,
{
strictSelection: false,
ariaLabel: LocalizedStrings.TARGETDATABASE,
actionLabel: localize('restoreDialog.toggleDatabaseNameDropdown', 'Select Database Toggle Dropdown')
}
);
this._databaseDropdown.onValueChange(s => {
this.databaseSelected(s);
});
this._databaseDropdown.onBlur(() => {
this.databaseSelected(this._databaseDropdown.value);
});
this._databaseDropdown.onFocus(() => {
this._onDatabaseListFocused.fire();
});
this._databaseDropdown.value = this.viewModel.targetDatabaseName;
attachEditableDropdownStyler(this._databaseDropdown, this._themeService);
this._destinationRestoreToInputBox = this.createInputBoxHelper(destinationElement, localize('restoreTo', "Restore to"));
// Restore plan section
let restorePlanElement: HTMLElement;
$().div({ class: 'restore-plan-section new-section' }, (restorePlanContainer) => {
restorePlanElement = restorePlanContainer.getHTMLElement();
this.createLabelElement(restorePlanContainer, localize('restorePlan', 'Restore plan'), true);
this.createLabelElement(restorePlanContainer, localize('backupSetsToRestore', 'Backup sets to restore'));
const restorePlanElement = DOM.$('.restore-plan-section.new-section');
this.createLabelElement(restorePlanElement, localize('restorePlan', "Restore plan"), true);
this.createLabelElement(restorePlanElement, localize('backupSetsToRestore', "Backup sets to restore"));
// Backup sets table
restorePlanContainer.div({ class: 'dialog-input-section restore-list' }, (labelContainer) => {
this._restorePlanTableContainer = labelContainer.getHTMLElement();
labelContainer.hide();
this._restorePlanData = new TableDataView<Slick.SlickData>();
this._restorePlanTable = new Table<Slick.SlickData>(labelContainer.getHTMLElement(),
{ dataProvider: this._restorePlanData, columns: this._restorePlanColumn }, { enableColumnReorder: false });
this._restorePlanTable.setSelectionModel(new RowSelectionModel({ selectActiveRow: false }));
this._restorePlanTable.onSelectedRowsChanged((e, data) => this.backupFileCheckboxChanged(e, data));
});
});
// Backup sets table
this._restorePlanTableContainer = DOM.append(restorePlanElement, DOM.$('.dialog-input-section.restore-list'));
DOM.hide(this._restorePlanTableContainer);
this._restorePlanData = new TableDataView<Slick.SlickData>();
this._restorePlanTable = new Table<Slick.SlickData>(this._restorePlanTableContainer,
{ dataProvider: this._restorePlanData, columns: this._restorePlanColumn }, { enableColumnReorder: false });
this._restorePlanTable.setSelectionModel(new RowSelectionModel({ selectActiveRow: false }));
this._restorePlanTable.onSelectedRowsChanged((e, data) => this.backupFileCheckboxChanged(e, data));
// Content in general tab
let generalTab = $('.restore-dialog');
const generalTab = DOM.$('.restore-dialog');
generalTab.append(sourceElement);
generalTab.append(destinationElement);
generalTab.append(restorePlanElement);
// Content in file tab
let fileContentElement: HTMLElement;
$().div({ class: 'restore-dialog' }, (builder) => {
fileContentElement = builder.getHTMLElement();
const fileContentElement = DOM.$('.restore-dialog');
const restoreAsSectionContainer = DOM.append(fileContentElement, DOM.$('.new-section'));
// Restore database file as section
builder.div({ class: 'new-section' }, (sectionContainer) => {
this.createLabelElement(sectionContainer, localize('restoreDatabaseFileAs', 'Restore database files as'), true);
this.createOptionControl(sectionContainer, this._relocateDatabaseFilesOption);
sectionContainer.div({ class: 'sub-section' }, (subSectionContainer) => {
this.createOptionControl(subSectionContainer, this._relocatedDataFileFolderOption);
this.createOptionControl(subSectionContainer, this._relocatedLogFileFolderOption);
});
});
this.createLabelElement(restoreAsSectionContainer, localize('restoreDatabaseFileAs', "Restore database files as"), true);
this.createOptionControl(restoreAsSectionContainer, this._relocateDatabaseFilesOption);
const subSectionContainer = DOM.append(restoreAsSectionContainer, DOM.$('.sub-section'));
this.createOptionControl(subSectionContainer, this._relocatedDataFileFolderOption);
this.createOptionControl(subSectionContainer, this._relocatedLogFileFolderOption);
// Restore database file details section
builder.div({ class: 'new-section' }, (sectionContainer) => {
this.createLabelElement(sectionContainer, localize('restoreDatabaseFileDetails', 'Restore database file details'), true);
// file list table
sectionContainer.div({ class: 'dialog-input-section restore-list' }, (fileNameContainer) => {
this._fileListTableContainer = fileNameContainer.getHTMLElement();
fileNameContainer.hide();
let logicalFileName = localize('logicalFileName', 'Logical file Name');
let fileType = localize('fileType', 'File type');
let originalFileName = localize('originalFileName', 'Original File Name');
let restoreAs = localize('restoreAs', 'Restore as');
var columns = [{
id: 'logicalFileName',
name: logicalFileName,
field: 'logicalFileName'
}, {
id: 'fileType',
name: fileType,
field: 'fileType'
}, {
id: 'originalFileName',
name: originalFileName,
field: 'originalFileName'
}, {
id: 'restoreAs',
name: restoreAs,
field: 'restoreAs'
}];
this._fileListData = new TableDataView<FileListElement>();
this._fileListTable = new Table<FileListElement>(fileNameContainer.getHTMLElement(),
{ dataProvider: this._fileListData, columns }, { enableColumnReorder: false });
this._fileListTable.setSelectionModel(new RowSelectionModel());
});
});
});
// Restore database file details section
const restoreFileSectionContainer = DOM.append(fileContentElement, DOM.$('.new-section'));
this.createLabelElement(restoreFileSectionContainer, localize('restoreDatabaseFileDetails', "Restore database file details"), true);
// file list table
this._fileListTableContainer = DOM.append(restoreFileSectionContainer, DOM.$('.dialog-input-section.restore-list'));
DOM.hide(this._fileListTableContainer);
const logicalFileName = localize('logicalFileName', "Logical file Name");
const fileType = localize('fileType', "File type");
const originalFileName = localize('originalFileName', "Original File Name");
const restoreAs = localize('restoreAs', "Restore as");
const columns = [{
id: 'logicalFileName',
name: logicalFileName,
field: 'logicalFileName'
}, {
id: 'fileType',
name: fileType,
field: 'fileType'
}, {
id: 'originalFileName',
name: originalFileName,
field: 'originalFileName'
}, {
id: 'restoreAs',
name: restoreAs,
field: 'restoreAs'
}];
this._fileListData = new TableDataView<FileListElement>();
this._fileListTable = new Table<FileListElement>(this._fileListTableContainer,
{ dataProvider: this._fileListData, columns }, { enableColumnReorder: false });
this._fileListTable.setSelectionModel(new RowSelectionModel());
// Content in options tab
let optionsContentElement: HTMLElement;
$().div({ class: 'restore-dialog' }, (builder) => {
optionsContentElement = builder.getHTMLElement();
const optionsContentElement = DOM.$('.restore-dialog');
// Restore options section
const restoreOptions = DOM.append(optionsContentElement, DOM.$('.new-section'));
this.createLabelElement(restoreOptions, localize('restoreOptions', "Restore options"), true);
this.createOptionControl(restoreOptions, this._withReplaceDatabaseOption);
this.createOptionControl(restoreOptions, this._withKeepReplicationOption);
this.createOptionControl(restoreOptions, this._withRestrictedUserOption);
this.createOptionControl(restoreOptions, this._recoveryStateOption);
// Restore options section
builder.div({ class: 'new-section' }, (sectionContainer) => {
this.createLabelElement(sectionContainer, localize('restoreOptions', 'Restore options'), true);
this.createOptionControl(sectionContainer, this._withReplaceDatabaseOption);
this.createOptionControl(sectionContainer, this._withKeepReplicationOption);
this.createOptionControl(sectionContainer, this._withRestrictedUserOption);
this.createOptionControl(sectionContainer, this._recoveryStateOption);
this.createOptionControl(DOM.append(restoreOptions, DOM.$('.sub-section')), this._standbyFileOption);
sectionContainer.div({ class: 'sub-section' }, (subSectionContainer) => {
this.createOptionControl(subSectionContainer, this._standbyFileOption);
});
});
// Tail-Log backup section
const tailLog = DOM.append(optionsContentElement, DOM.$('.new-section'));
this.createLabelElement(tailLog, localize('taillogBackup', "Tail-Log backup"), true);
this.createOptionControl(tailLog, this._takeTaillogBackupOption);
const tailLogOptions = DOM.append(tailLog, DOM.$('.sub-section'));
this.createOptionControl(tailLogOptions, this._tailLogWithNoRecoveryOption);
this.createOptionControl(tailLogOptions, this._tailLogBackupFileOption);
// Tail-Log backup section
builder.div({ class: 'new-section' }, (sectionContainer) => {
this.createLabelElement(sectionContainer, localize('taillogBackup', 'Tail-Log backup'), true);
this.createOptionControl(sectionContainer, this._takeTaillogBackupOption);
sectionContainer.div({ class: 'sub-section' }, (subSectionContainer) => {
this.createOptionControl(subSectionContainer, this._tailLogWithNoRecoveryOption);
this.createOptionControl(subSectionContainer, this._tailLogBackupFileOption);
});
});
// Server connections section
const serverConnections = DOM.append(optionsContentElement, DOM.$('.new-section'));
this.createLabelElement(serverConnections, localize('serverConnection', "Server connections"), true);
this.createOptionControl(serverConnections, this._closeExistingConnectionsOption);
// Server connections section
builder.div({ class: 'new-section' }, (sectionContainer) => {
this.createLabelElement(sectionContainer, localize('serverConnection', 'Server connections'), true);
this.createOptionControl(sectionContainer, this._closeExistingConnectionsOption);
});
});
let restorePanel = $('.restore-panel');
container.appendChild(restorePanel.getHTMLElement());
this._panel = new TabbedPanel(restorePanel.getHTMLElement());
const restorePanel = DOM.$('.restore-panel');
container.appendChild(restorePanel);
this._panel = new TabbedPanel(restorePanel);
this._generalTabId = this._panel.pushTab({
identifier: 'general',
title: localize('generalTitle', 'General'),
view: {
render: c => {
generalTab.appendTo(c);
DOM.append(c, generalTab);
},
layout: () => { }
}
});
let fileTab = this._panel.pushTab({
const fileTab = this._panel.pushTab({
identifier: 'fileContent',
title: localize('filesTitle', 'Files'),
view: {
@@ -469,19 +419,17 @@ export class RestoreDialog extends Modal {
this._databaseDropdown.values = vals;
}
private createLabelElement(container: Builder, content: string, isHeader?: boolean) {
private createLabelElement(container: HTMLElement, content: string, isHeader?: boolean) {
let className = 'dialog-label';
if (isHeader) {
className += ' header';
}
container.div({ class: className }, (labelContainer) => {
labelContainer.text(content);
});
DOM.append(container, DOM.$(`.${className}`)).innerText = content;
}
private createOptionControl(container: Builder, optionName: string): void {
let option = this.viewModel.getOptionMetadata(optionName);
let propertyWidget: any;
private createOptionControl(container: HTMLElement, optionName: string): void {
const option = this.viewModel.getOptionMetadata(optionName);
let propertyWidget: SelectBox | InputBox | Checkbox;
switch (option.valueType) {
case ServiceOptionType.boolean:
propertyWidget = this.createCheckBoxHelper(container, option.description,
@@ -522,63 +470,46 @@ export class RestoreDialog extends Modal {
}
}
private createCheckBoxHelper(container: Builder, label: string, isChecked: boolean, onCheck: (viaKeyboard: boolean) => void): Checkbox {
let checkbox: Checkbox;
container.div({ class: 'dialog-input-section' }, (inputCellContainer) => {
checkbox = new Checkbox(inputCellContainer.getHTMLElement(), {
label: label,
checked: isChecked,
onChange: onCheck,
ariaLabel: label
});
private createCheckBoxHelper(container: HTMLElement, label: string, isChecked: boolean, onCheck: (viaKeyboard: boolean) => void): Checkbox {
const checkbox = new Checkbox(DOM.append(container, DOM.$('.dialog-input-section')), {
label: label,
checked: isChecked,
onChange: onCheck,
ariaLabel: label
});
this._register(attachCheckboxStyler(checkbox, this._themeService));
return checkbox;
}
private createSelectBoxHelper(container: Builder, label: string, options: string[], selectedOption: string): SelectBox {
let selectBox: SelectBox;
container.div({ class: 'dialog-input-section' }, (inputContainer) => {
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => {
labelContainer.text(label);
});
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => {
selectBox = new SelectBox(options, selectedOption, this._contextViewService, inputCellContainer.getHTMLElement(), { ariaLabel: label });
selectBox.render(inputCellContainer.getHTMLElement());
});
});
private createSelectBoxHelper(container: HTMLElement, label: string, options: string[], selectedOption: string): SelectBox {
const inputContainer = DOM.append(container, DOM.$('.dialog-input-section'));
DOM.append(inputContainer, DOM.$('.dialog-label')).innerText = label;
const inputCellContainer = DOM.append(inputContainer, DOM.$('.dialog-input'));
const selectBox = new SelectBox(options, selectedOption, this._contextViewService, inputCellContainer, { ariaLabel: label });
selectBox.render(inputCellContainer);
return selectBox;
}
private createInputBoxHelper(container: Builder, label: string, options?: IInputOptions): InputBox {
let inputBox: InputBox;
let ariaOptions = {
private createInputBoxHelper(container: HTMLElement, label: string, options?: IInputOptions): InputBox {
const ariaOptions = {
ariaLabel: label
};
container.div({ class: 'dialog-input-section' }, (inputContainer) => {
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => {
labelContainer.safeInnerHtml(label);
});
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => {
inputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, mixin(ariaOptions, options));
});
});
return inputBox;
const inputContainer = DOM.append(container, DOM.$('.dialog-input-section'));
DOM.append(inputContainer, DOM.$('.dialog-label')).innerText = label;
return new InputBox(DOM.append(inputContainer, DOM.$('.dialog-input')), this._contextViewService, mixin(ariaOptions, options));
}
private clearRestorePlanDataTable(): void {
if (this._restorePlanData.getLength() > 0) {
this._restorePlanData.clear();
new Builder(this._restorePlanTableContainer).hide();
DOM.hide(this._restorePlanTableContainer);
}
}
private clearFileListTable(): void {
if (this._fileListData.getLength() > 0) {
this._fileListData.clear();
new Builder(this._fileListTableContainer).hide();
DOM.hide(this._fileListTableContainer);
}
}
@@ -672,7 +603,7 @@ export class RestoreDialog extends Modal {
}
private onFileBrowsed(filepath: string) {
var oldFilePath = this._filePathInputBox.value;
const oldFilePath = this._filePathInputBox.value;
if (strings.isFalsyOrWhitespace(this._filePathInputBox.value)) {
this._filePathInputBox.value = filepath;
} else {
@@ -708,10 +639,10 @@ export class RestoreDialog extends Modal {
this.removeErrorMessage();
if (selectedRestoreFrom === this._backupFileTitle) {
this.viewModel.onRestoreFromChanged(true);
new Builder(this._restoreFromBackupFileElement).show();
DOM.show(this._restoreFromBackupFileElement);
} else {
this.viewModel.onRestoreFromChanged(false);
new Builder(this._restoreFromBackupFileElement).hide();
DOM.hide(this._restoreFromBackupFileElement);
}
this.resetRestoreContent();
}
@@ -821,7 +752,7 @@ export class RestoreDialog extends Modal {
}
private updateRestoreOption(optionParam: RestoreOptionParam) {
let widget = this._optionsMap[optionParam.optionName];
const widget = this._optionsMap[optionParam.optionName];
if (widget) {
if (widget instanceof Checkbox) {
(<Checkbox>widget).checked = optionParam.value;
@@ -847,7 +778,7 @@ export class RestoreDialog extends Modal {
private updateRestoreDatabaseFiles(dbFiles: azdata.RestoreDatabaseFileInfo[]) {
this.clearFileListTable();
if (dbFiles && dbFiles.length > 0) {
let data = [];
const data = [];
for (let i = 0; i < dbFiles.length; i++) {
data[i] = {
logicalFileName: dbFiles[i].logicalFileName,
@@ -856,7 +787,7 @@ export class RestoreDialog extends Modal {
restoreAs: dbFiles[i].restoreAsFileName
};
}
new Builder(this._fileListTableContainer).show();
DOM.show(this._fileListTableContainer);
this._fileListData.push(data);
// Select the first row for the table by default
@@ -867,7 +798,7 @@ export class RestoreDialog extends Modal {
private updateBackupSetsToRestore(backupSetsToRestore: azdata.DatabaseFileInfo[]) {
if (this._isBackupFileCheckboxChanged) {
let selectedRow = [];
const selectedRow = [];
for (let i = 0; i < backupSetsToRestore.length; i++) {
if (backupSetsToRestore[i].isSelected) {
selectedRow.push(i);
@@ -878,7 +809,7 @@ export class RestoreDialog extends Modal {
this.clearRestorePlanDataTable();
if (backupSetsToRestore && backupSetsToRestore.length > 0) {
if (!this._restorePlanColumn) {
let firstRow = backupSetsToRestore[0];
const firstRow = backupSetsToRestore[0];
this._restorePlanColumn = firstRow.properties.map(item => {
return {
id: item.propertyName,
@@ -887,18 +818,18 @@ export class RestoreDialog extends Modal {
};
});
let checkboxSelectColumn = new CheckboxSelectColumn({ title: this._restoreLabel, toolTip: this._restoreLabel, width: 15 });
const checkboxSelectColumn = new CheckboxSelectColumn({ title: this._restoreLabel, toolTip: this._restoreLabel, width: 15 });
this._restorePlanColumn.unshift(checkboxSelectColumn.getColumnDefinition());
this._restorePlanTable.columns = this._restorePlanColumn;
this._restorePlanTable.registerPlugin(checkboxSelectColumn);
this._restorePlanTable.autosizeColumns();
}
let data = [];
let selectedRow = [];
const data = [];
const selectedRow = [];
for (let i = 0; i < backupSetsToRestore.length; i++) {
let backupFile = backupSetsToRestore[i];
let newData = {};
const backupFile = backupSetsToRestore[i];
const newData = {};
for (let j = 0; j < backupFile.properties.length; j++) {
newData[backupFile.properties[j].propertyName] = backupFile.properties[j].propertyValueDisplayName;
}
@@ -907,7 +838,7 @@ export class RestoreDialog extends Modal {
selectedRow.push(i);
}
}
new Builder(this._restorePlanTableContainer).show();
DOM.show(this._restorePlanTableContainer);
this._restorePlanData.push(data);
this._restorePlanTable.setSelectedRows(selectedRow);
this._restorePlanTable.setActiveCell(selectedRow[0], 0);

View File

@@ -10,7 +10,6 @@ import * as TreeDefaults from 'vs/base/parts/tree/browser/treeDefaults';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { generateUuid } from 'vs/base/common/uuid';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { $ } from 'sql/base/browser/builder';
export class JobStepsViewRow {
public stepId: string;
@@ -135,7 +134,7 @@ export class JobStepsViewRenderer implements tree.IRenderer {
stepIdCol.className += ' step-column-heading';
stepMessageCol.className += ' step-column-heading';
}
$(templateData.label).empty();
DOM.clearNode(templateData.label);
templateData.label.appendChild(stepIdCol);
templateData.label.appendChild(stepNameCol);
templateData.label.appendChild(stepMessageCol);

View File

@@ -5,17 +5,16 @@
import 'vs/css!./dom';
import 'vs/css!./highlight';
import 'vs/css!./markdown';
import {
Component, Input, Inject, ChangeDetectorRef, forwardRef, ComponentFactoryResolver,
ViewChild, ViewChildren, ElementRef, Injector, OnDestroy, QueryList
Component, Input, Inject, ChangeDetectorRef, forwardRef, ElementRef, OnDestroy
} from '@angular/core';
import * as azdata from 'azdata';
import * as DOM from 'vs/base/browser/dom';
import { $, Builder } from 'sql/base/browser/builder';
import { ComponentBase } from 'sql/parts/modelComponents/componentBase';
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
import { IComponent, IComponentDescriptor, IModelStore } from 'sql/parts/modelComponents/interfaces';
@Component({
template: '',
@@ -25,8 +24,8 @@ export default class DomComponent extends ComponentBase implements IComponent, O
@Input() descriptor: IComponentDescriptor;
@Input() modelStore: IModelStore;
private _renderedHtml: string;
private _rootElement: Builder;
private _bodyElement: Builder;
private _rootElement: HTMLElement;
private _bodyElement: HTMLElement;
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
@@ -48,8 +47,8 @@ export default class DomComponent extends ComponentBase implements IComponent, O
}
private createDomElement() {
this._rootElement = new Builder(this._el.nativeElement);
this._bodyElement = $('.dom-body');
this._rootElement = this._el.nativeElement;
this._bodyElement = DOM.$('.dom-body');
this._rootElement.append(this._bodyElement);
}
@@ -57,14 +56,14 @@ export default class DomComponent extends ComponentBase implements IComponent, O
private setHtml(): void {
if (this.html) {
this._renderedHtml = this.html;
this._bodyElement.innerHtml(this._renderedHtml);
this._bodyElement.innerHTML = this._renderedHtml;
}
}
/// IComponent implementation
public layout(): void {
super.layout();
let element = <HTMLElement>this._el.nativeElement;
const element = <HTMLElement>this._el.nativeElement;
element.style.width = this.getWidth();
element.style.height = this.getHeight();
}

View File

@@ -3,9 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/serverGroupDialog';
import { Builder } from 'sql/base/browser/builder';
import { Checkbox } from 'vs/base/browser/ui/checkbox/checkbox';
import { MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
import * as DOM from 'vs/base/browser/dom';
@@ -17,19 +16,18 @@ 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 { ILayoutService } from 'vs/platform/layout/browser/layoutService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
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 { ServerGroupViewModel } from 'sql/parts/objectExplorer/serverGroupDialog/serverGroupViewModel';
import { attachButtonStyler, attachModalDialogStyler } from 'sql/platform/theme/common/styler';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
export class ServerGroupDialog extends Modal {
private _bodyBuilder: Builder;
private _addServerButton: Button;
private _closeButton: Button;
private _colorCheckBoxesMap: Array<{ color: string, checkbox: Checkbox }> = [];
@@ -38,7 +36,7 @@ export class ServerGroupDialog extends Modal {
private _groupDescriptionInputBox: InputBox;
private _viewModel: ServerGroupViewModel;
private _skipGroupNameValidation: boolean = false;
private $serverGroupContainer: Builder;
private _serverGroupContainer: HTMLElement;
private _onAddServerGroup = new Emitter<void>();
public onAddServerGroup: Event<void> = this._onAddServerGroup.event;
@@ -50,7 +48,7 @@ export class ServerGroupDialog extends Modal {
public onCloseEvent: Event<void> = this._onCloseEvent.event;
constructor(
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@ILayoutService layoutService: ILayoutService,
@IThemeService themeService: IThemeService,
@IContextViewService private _contextViewService: IContextViewService,
@ITelemetryService telemetryService: ITelemetryService,
@@ -63,8 +61,8 @@ export class ServerGroupDialog extends Modal {
public render() {
super.render();
attachModalDialogStyler(this, this._themeService);
let okLabel = localize('serverGroup.ok', 'OK');
let cancelLabel = localize('serverGroup.cancel', 'Cancel');
const okLabel = localize('serverGroup.ok', "OK");
const cancelLabel = localize('serverGroup.cancel', "Cancel");
this._addServerButton = this.addFooterButton(okLabel, () => this.addGroup());
this._closeButton = this.addFooterButton(cancelLabel, () => this.cancel());
this.registerListeners();
@@ -75,68 +73,56 @@ export class ServerGroupDialog extends Modal {
}
protected renderBody(container: HTMLElement) {
new Builder(container).div({ class: 'server-group-dialog' }, (builder) => {
this._bodyBuilder = builder;
});
const body = DOM.append(container, DOM.$('.server-group-dialog'));
// Connection Group Name
let serverGroupNameLabel = localize('connectionGroupName', 'Server group name');
this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => {
labelContainer.text(serverGroupNameLabel);
});
this._bodyBuilder.div({ class: 'input-divider' }, (inputCellContainer) => {
let errorMessage = localize('MissingGroupNameError', 'Group name is required.');
this._groupNameInputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, {
validationOptions: {
validation: (value: string) => !value && !this._skipGroupNameValidation ? ({ type: MessageType.ERROR, content: errorMessage }) : null
},
ariaLabel: serverGroupNameLabel
});
const serverGroupNameLabel = localize('connectionGroupName', "Server group name");
DOM.append(body, DOM.$('.dialog-label')).innerText = serverGroupNameLabel;
this._groupNameInputBox = new InputBox(DOM.append(body, DOM.$('.input-divider')), this._contextViewService, {
validationOptions: {
validation: (value: string) => !value && !this._skipGroupNameValidation ? ({ type: MessageType.ERROR, content: localize('MissingGroupNameError', "Group name is required.") }) : null
},
ariaLabel: serverGroupNameLabel
});
// Connection Group Description
let groupDescriptionLabel = localize('groupDescription', 'Group description');
this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => {
labelContainer.text(groupDescriptionLabel);
});
this._bodyBuilder.div({ class: 'input-divider' }, (inputCellContainer) => {
this._groupDescriptionInputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, {
ariaLabel: groupDescriptionLabel
});
const groupDescriptionLabel = localize('groupDescription', "Group description");
DOM.append(body, DOM.$('.dialog-label')).innerText = groupDescriptionLabel;
this._groupDescriptionInputBox = new InputBox(DOM.append(body, DOM.$('.input-divider')), this._contextViewService, {
ariaLabel: groupDescriptionLabel
});
// Connection Group Color
this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => {
let groupColorLabel = localize('groupColor', 'Group color');
labelContainer.text(groupColorLabel);
});
const groupColorLabel = localize('groupColor', "Group color");
DOM.append(body, DOM.$('.dialog-label')).innerText = groupColorLabel;
this._bodyBuilder.div({ class: 'group-color-options' }, (groupColorContainer) => {
this.$serverGroupContainer = groupColorContainer;
this.fillGroupColors(groupColorContainer.getHTMLElement());
});
this._serverGroupContainer = DOM.append(body, DOM.$('.group-color-options'));
this.fillGroupColors(this._serverGroupContainer);
this._bodyBuilder.on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
DOM.addStandardDisposableListener(body, DOM.EventType.KEY_DOWN, (event: StandardKeyboardEvent) => {
if (event.equals(KeyMod.Shift | KeyCode.Tab)) {
this.preventDefaultKeyboardEvent(e);
this.preventDefaultKeyboardEvent(event);
this.focusPrevious();
} else if (event.equals(KeyCode.Tab)) {
this.preventDefaultKeyboardEvent(e);
this.preventDefaultKeyboardEvent(event);
this.focusNext();
} else if (event.equals(KeyCode.RightArrow) || event.equals(KeyCode.LeftArrow)) {
this.preventDefaultKeyboardEvent(e);
this.preventDefaultKeyboardEvent(event);
this.focusNextColor(event.equals(KeyCode.RightArrow));
}
});
}
private preventDefaultKeyboardEvent(e: KeyboardEvent) {
private preventDefaultKeyboardEvent(e: StandardKeyboardEvent) {
e.preventDefault();
e.stopPropagation();
}
private isFocusOnColors(): boolean {
var result = false;
let result = false;
this._colorCheckBoxesMap.forEach(({ checkbox }) => {
if (document.activeElement === checkbox.domNode) {
result = true;
@@ -229,9 +215,9 @@ export class ServerGroupDialog extends Modal {
private fillGroupColors(container: HTMLElement): void {
for (let i = 0; i < this._viewModel.colors.length; i++) {
let color = this._viewModel.colors[i];
const color = this._viewModel.colors[i];
let colorCheckBox = new Checkbox({
const colorCheckBox = new Checkbox({
actionClassName: 'server-group-color',
title: color,
isChecked: false
@@ -277,9 +263,9 @@ export class ServerGroupDialog extends Modal {
}
public set viewModel(theViewModel: ServerGroupViewModel) {
this._viewModel = theViewModel;
if (this.$serverGroupContainer) {
this.$serverGroupContainer.clearChildren();
this.fillGroupColors(this.$serverGroupContainer.getHTMLElement());
if (this._serverGroupContainer) {
DOM.clearNode(this._serverGroupContainer);
this.fillGroupColors(this._serverGroupContainer);
}
}

View File

@@ -6,7 +6,6 @@
import 'vs/css!./media/serverTreeActions';
import * as errors from 'vs/base/common/errors';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import * as builder from 'sql/base/browser/builder';
import Severity from 'vs/base/common/severity';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachListStyler } from 'vs/platform/theme/common/styler';
@@ -14,6 +13,8 @@ import { ITree } from 'vs/base/parts/tree/browser/tree';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { localize } from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { Event, Emitter } from 'vs/base/common/event';
import { append, $, hide, show } from 'vs/base/browser/dom';
import { ConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
@@ -27,28 +28,27 @@ import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/co
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { Button } from 'sql/base/browser/ui/button/button';
import { attachButtonStyler } from 'sql/platform/theme/common/styler';
import { Event, Emitter } from 'vs/base/common/event';
import { TreeNode, TreeItemCollapsibleState } from 'sql/parts/objectExplorer/common/treeNode';
import { SERVER_GROUP_CONFIG, SERVER_GROUP_AUTOEXPAND_CONFIG } from 'sql/parts/objectExplorer/serverGroupDialog/serverGroup.contribution';
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
import { ServerTreeActionProvider } from 'sql/parts/objectExplorer/viewlet/serverTreeActionProvider';
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
const $ = builder.$;
import { isHidden } from 'sql/base/browser/dom';
/**
* ServerTreeview implements the dynamic tree view.
*/
export class ServerTreeView {
public messages: builder.Builder;
private _buttonSection: builder.Builder;
public messages: HTMLElement;
private _buttonSection: HTMLElement;
private _treeSelectionHandler: TreeSelectionHandler;
private _activeConnectionsFilterAction: ActiveConnectionsFilterAction;
private _tree: ITree;
private _toDispose: IDisposable[] = [];
private _onSelectionOrFocusChange: Emitter<void>;
private _actionProvider: ServerTreeActionProvider;
constructor(
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@IInstantiationService private _instantiationService: IInstantiationService,
@@ -101,15 +101,17 @@ export class ServerTreeView {
*/
public renderBody(container: HTMLElement): Thenable<void> {
// Add div to display no connections found message and hide it by default
this.messages = $('div.title').appendTo(container);
$('span').style('padding-left', '10px').text('No connections found.').appendTo(this.messages);
this.messages.hide();
this.messages = append(container, $('.title'));
const messageText = append(this.messages, $('span'));
messageText.style.paddingLeft = '10px';
messageText.innerText = localize('servers.noConnections', "No connections found.");
hide(this.messages);
if (!this._connectionManagementService.hasRegisteredServers()) {
this._activeConnectionsFilterAction.enabled = false;
this._buttonSection = $('div.button-section').appendTo(container);
var connectButton = new Button(this._buttonSection.getHTMLElement());
connectButton.label = localize('serverTree.addConnection', 'Add Connection');
this._buttonSection = append(container, $('.button-section'));
const connectButton = new Button(this._buttonSection);
connectButton.label = localize('serverTree.addConnection', "Add Connection");
this._toDispose.push(attachButtonStyler(connectButton, this._themeService));
this._toDispose.push(connectButton.onDidClick(() => {
this._connectionManagementService.showConnectionDialog();
@@ -124,41 +126,41 @@ export class ServerTreeView {
// Theme styler
this._toDispose.push(attachListStyler(this._tree, this._themeService));
const self = this;
// Refresh Tree when these events are emitted
this._toDispose.push(this._connectionManagementService.onAddConnectionProfile((newProfile: IConnectionProfile) => {
self.handleAddConnectionProfile(newProfile);
this.handleAddConnectionProfile(newProfile);
}));
this._toDispose.push(this._connectionManagementService.onDeleteConnectionProfile(() => {
self.refreshTree();
this.refreshTree();
}));
this._toDispose.push(this._connectionManagementService.onDisconnect((connectionParams) => {
if (self.isObjectExplorerConnectionUri(connectionParams.connectionUri)) {
self.deleteObjectExplorerNodeAndRefreshTree(connectionParams.connectionProfile);
if (this.isObjectExplorerConnectionUri(connectionParams.connectionUri)) {
this.deleteObjectExplorerNodeAndRefreshTree(connectionParams.connectionProfile);
}
}));
if (this._objectExplorerService && this._objectExplorerService.onUpdateObjectExplorerNodes) {
this._toDispose.push(this._objectExplorerService.onUpdateObjectExplorerNodes(args => {
if (args.errorMessage) {
self.showError(args.errorMessage);
this.showError(args.errorMessage);
}
if (args.connection) {
self.onObjectExplorerSessionCreated(args.connection);
this.onObjectExplorerSessionCreated(args.connection);
}
}));
}
return new Promise<void>((resolve, reject) => {
self.refreshTree();
let root = <ConnectionProfileGroup>self._tree.getInput();
let expandGroups: boolean = self._configurationService.getValue(SERVER_GROUP_CONFIG)[SERVER_GROUP_AUTOEXPAND_CONFIG];
return new Promise<void>((resolve, reject) => {
this.refreshTree();
const root = <ConnectionProfileGroup>this._tree.getInput();
const expandGroups: boolean = this._configurationService.getValue(SERVER_GROUP_CONFIG)[SERVER_GROUP_AUTOEXPAND_CONFIG];
if (expandGroups) {
self._tree.expandAll(ConnectionProfileGroup.getSubgroups(root));
this._tree.expandAll(ConnectionProfileGroup.getSubgroups(root));
}
if (root && !root.hasValidConnections) {
self._treeSelectionHandler.onTreeActionStateChange(true);
this._treeSelectionHandler.onTreeActionStateChange(true);
resolve();
} else {
resolve();
@@ -174,20 +176,20 @@ export class ServerTreeView {
private async handleAddConnectionProfile(newProfile: IConnectionProfile): Promise<void> {
if (newProfile) {
let groups = this._connectionManagementService.getConnectionGroups();
let profile = ConnectionUtils.findProfileInGroup(newProfile, groups);
const groups = this._connectionManagementService.getConnectionGroups();
const profile = ConnectionUtils.findProfileInGroup(newProfile, groups);
if (profile) {
newProfile = profile;
}
}
if (this._buttonSection) {
this._buttonSection.getHTMLElement().style.display = 'none';
hide(this._buttonSection);
this._activeConnectionsFilterAction.enabled = true;
}
let currentSelections = this._tree.getSelection();
let currentSelectedElement = currentSelections && currentSelections.length >= 1 ? currentSelections[0] : undefined;
let newProfileIsSelected = currentSelectedElement && newProfile ? currentSelectedElement.id === newProfile.id : false;
const currentSelections = this._tree.getSelection();
const currentSelectedElement = currentSelections && currentSelections.length >= 1 ? currentSelections[0] : undefined;
const newProfileIsSelected = currentSelectedElement && newProfile ? currentSelectedElement.id === newProfile.id : false;
if (newProfile && currentSelectedElement && !newProfileIsSelected) {
this._tree.clearSelection();
}
@@ -205,9 +207,9 @@ export class ServerTreeView {
}
private getConnectionInTreeInput(connectionId: string): ConnectionProfile {
let root = TreeUpdateUtils.getTreeInput(this._connectionManagementService);
let connections = ConnectionProfileGroup.getConnectionsInGroup(root);
let results = connections.filter(con => {
const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService);
const connections = ConnectionProfileGroup.getConnectionsInGroup(root);
const results = connections.filter(con => {
if (connectionId === con.id) {
return true;
} else {
@@ -221,7 +223,7 @@ export class ServerTreeView {
}
private onObjectExplorerSessionCreated(connection: IConnectionProfile) {
var conn = this.getConnectionInTreeInput(connection.id);
const conn = this.getConnectionInTreeInput(connection.id);
if (conn) {
this._tree.refresh(conn).then(() => {
return this._tree.expand(conn).then(() => {
@@ -234,7 +236,7 @@ export class ServerTreeView {
}
public addObjectExplorerNodeAndRefreshTree(connection: IConnectionProfile): void {
this.messages.hide();
hide(this.messages);
if (!this._objectExplorerService.getObjectExplorerNode(connection)) {
this._objectExplorerService.updateObjectExplorerNodes(connection).then(() => {
// The oe request is sent. an event will be raised when the session is created
@@ -245,7 +247,7 @@ export class ServerTreeView {
public deleteObjectExplorerNodeAndRefreshTree(connection: IConnectionProfile): Thenable<void> {
if (connection) {
var conn = this.getConnectionInTreeInput(connection.id);
const conn = this.getConnectionInTreeInput(connection.id);
if (conn) {
return this._objectExplorerService.deleteObjectExplorerNode(conn).then(() => {
this._tree.collapse(conn);
@@ -257,7 +259,7 @@ export class ServerTreeView {
}
public refreshTree(): Promise<void> {
this.messages.hide();
hide(this.messages);
this.clearOtherActions();
return TreeUpdateUtils.registeredServerUpdate(this._tree, this._connectionManagementService);
}
@@ -273,7 +275,7 @@ export class ServerTreeView {
if (!treeInput || treeInput.length === 0) {
return undefined;
}
let result = treeInput.map(group => {
const result = treeInput.map(group => {
// Keep active/recent connections and remove the rest
if (group.connections) {
group.connections = group.connections.filter(con => {
@@ -305,28 +307,26 @@ export class ServerTreeView {
* Set tree elements based on the view (recent/active)
*/
public showFilteredTree(view: string): void {
const self = this;
this.messages.hide();
hide(this.messages);
// Clear other action views if user switched between two views
this.clearOtherActions(view);
let root = TreeUpdateUtils.getTreeInput(this._connectionManagementService);
const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService);
let treeInput: ConnectionProfileGroup = null;
if (root) {
// Filter results based on view
let filteredResults = this.filterConnections([root], view);
const filteredResults = this.filterConnections([root], view);
if (!filteredResults || !filteredResults[0]) {
this.messages.show();
this.messages.domFocus();
show(this.messages);
this.messages.focus();
} else {
treeInput = filteredResults[0];
}
this._tree.setInput(treeInput).then(() => {
if (this.messages.isHidden()) {
self._tree.getFocus();
self._tree.expandAll(ConnectionProfileGroup.getSubgroups(treeInput));
if (isHidden(this.messages)) {
this._tree.getFocus();
this._tree.expandAll(ConnectionProfileGroup.getSubgroups(treeInput));
} else {
self._tree.clearFocus();
this._tree.clearFocus();
}
}, errors.onUnexpectedError);
} else {
@@ -341,25 +341,24 @@ export class ServerTreeView {
if (!searchString) {
return;
}
const self = this;
this.messages.hide();
hide(this.messages);
// Clear other actions if user searched during other views
this.clearOtherActions();
// Filter connections based on search
let filteredResults = this.searchConnections(searchString);
const filteredResults = this.searchConnections(searchString);
if (!filteredResults || filteredResults.length === 0) {
this.messages.show();
this.messages.domFocus();
show(this.messages);
this.messages.focus();
}
// Add all connections to tree root and set tree input
let treeInput = new ConnectionProfileGroup('searchroot', undefined, 'searchroot', undefined, undefined);
const treeInput = new ConnectionProfileGroup('searchroot', undefined, 'searchroot', undefined, undefined);
treeInput.addConnections(filteredResults);
this._tree.setInput(treeInput).then(() => {
if (this.messages.isHidden()) {
self._tree.getFocus();
self._tree.expandAll(ConnectionProfileGroup.getSubgroups(treeInput));
if (isHidden(this.messages)) {
this._tree.getFocus();
this._tree.expandAll(ConnectionProfileGroup.getSubgroups(treeInput));
} else {
self._tree.clearFocus();
this._tree.clearFocus();
}
}, errors.onUnexpectedError);
}
@@ -369,9 +368,9 @@ export class ServerTreeView {
*/
private searchConnections(searchString: string): ConnectionProfile[] {
let root = TreeUpdateUtils.getTreeInput(this._connectionManagementService);
let connections = ConnectionProfileGroup.getConnectionsInGroup(root);
let results = connections.filter(con => {
const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService);
const connections = ConnectionProfileGroup.getConnectionsInGroup(root);
const results = connections.filter(con => {
if (searchString && (searchString.length > 0)) {
return this.isMatch(con, searchString);
} else {
@@ -499,4 +498,4 @@ export class ServerTreeView {
this._tree.dispose();
this._toDispose = dispose(this._toDispose);
}
}
}

View File

@@ -2,18 +2,18 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!sql/parts/profiler/media/profiler';
import { Modal } from 'sql/workbench/browser/modal/modal';
import { attachModalDialogStyler } from 'sql/platform/theme/common/styler';
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import * as nls from 'vs/nls';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { Builder } from 'sql/base/browser/builder';
import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
@@ -24,7 +24,6 @@ import { Event, Emitter } from 'vs/base/common/event';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
class EventItem {
@@ -209,8 +208,8 @@ class TreeRenderer implements IRenderer {
}
renderTemplate(tree: ITree, templateId: string, container: HTMLElement): RenderTemplate {
let data = Object.create(null);
let row = document.createElement('div');
const data = Object.create(null);
const row = document.createElement('div');
row.className = 'tree-row';
DOM.append(container, row);
data.toDispose = [];
@@ -301,13 +300,11 @@ class TreeDataSource implements IDataSource {
export class ProfilerColumnEditorDialog extends Modal {
private _selectBox: SelectBox;
private _selectedValue: number = 0;
private readonly _options = [
{ text: nls.localize('eventSort', "Sort by event") },
{ text: nls.localize('nameColumn', "Sort by column") }
];
private _tree: Tree;
private _input: ProfilerInput;
private _element: SessionItem;
private _treeContainer: HTMLElement;
@@ -330,29 +327,22 @@ export class ProfilerColumnEditorDialog extends Modal {
}
protected renderBody(container: HTMLElement): void {
let builder = new Builder(container);
builder.div({}, b => {
this._selectBox = new SelectBox(this._options, 0, this._contextViewService);
this._selectBox.render(b.getHTMLElement());
this._register(this._selectBox.onDidSelect(e => {
this._selectedValue = e.index;
this._element.changeSort(e.index === 0 ? 'event' : 'column');
this._tree.refresh(this._element, true);
}));
});
builder.div({ 'class': 'profiler-column-tree' }, b => {
this._treeContainer = b.getHTMLElement();
let renderer = new TreeRenderer();
this._tree = new Tree(this._treeContainer, { dataSource: new TreeDataSource(), renderer });
this._register(renderer.onSelectedChange(e => this._tree.refresh(e, true)));
this._register(attachListStyler(this._tree, this._themeService));
});
const body = DOM.append(container, DOM.$(''));
this._selectBox = new SelectBox(this._options, 0, this._contextViewService);
this._selectBox.render(body);
this._register(this._selectBox.onDidSelect(e => {
this._element.changeSort(e.index === 0 ? 'event' : 'column');
this._tree.refresh(this._element, true);
}));
this._treeContainer = DOM.append(body, DOM.$('.profiler-column-tree'));
const renderer = new TreeRenderer();
this._tree = new Tree(this._treeContainer, { dataSource: new TreeDataSource(), renderer });
this._register(renderer.onSelectedChange(e => this._tree.refresh(e, true)));
this._register(attachListStyler(this._tree, this._themeService));
}
public open(input: ProfilerInput): void {
super.show();
this._input = input;
this._updateList();
}

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!sql/media/icons/common-icons';
import 'vs/css!./media/profilerFilterDialog';
import { Button } from 'sql/base/browser/ui/button/button';
@@ -11,7 +10,6 @@ import { Modal } from 'sql/workbench/browser/modal/modal';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { attachButtonStyler, attachModalDialogStyler, attachInputBoxStyler } from 'sql/platform/theme/common/styler';
import { KeyCode } from 'vs/base/common/keyCodes';
import { Builder } from 'sql/base/browser/builder';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -29,19 +27,19 @@ import { ProfilerFilter, ProfilerFilterClause, ProfilerFilterClauseOperator } fr
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
const ClearText: string = localize('profilerFilterDialog.clear', 'Clear All');
const ApplyText: string = localize('profilerFilterDialog.apply', 'Apply');
const OkText: string = localize('profilerFilterDialog.ok', 'OK');
const CancelText: string = localize('profilerFilterDialog.cancel', 'Cancel');
const DialogTitle: string = localize('profilerFilterDialog.title', 'Filters');
const RemoveText: string = localize('profilerFilterDialog.remove', 'Remove');
const AddText: string = localize('profilerFilterDialog.add', 'Add');
const AddClausePromptText: string = localize('profilerFilterDialog.addClauseText', 'Click here to add a clause');
const ClearText: string = localize('profilerFilterDialog.clear', "Clear All");
const ApplyText: string = localize('profilerFilterDialog.apply', "Apply");
const OkText: string = localize('profilerFilterDialog.ok', "OK");
const CancelText: string = localize('profilerFilterDialog.cancel', "Cancel");
const DialogTitle: string = localize('profilerFilterDialog.title', "Filters");
const RemoveText: string = localize('profilerFilterDialog.remove', "Remove");
const AddText: string = localize('profilerFilterDialog.add', "Add");
const AddClausePromptText: string = localize('profilerFilterDialog.addClauseText', "Click here to add a clause");
const TitleIconClass: string = 'icon filterLabel';
const FieldText: string = localize('profilerFilterDialog.fieldColumn', 'Field');
const OperatorText: string = localize('profilerFilterDialog.operatorColumn', 'Operator');
const ValueText: string = localize('profilerFilterDialog.valueColumn', 'Value');
const FieldText: string = localize('profilerFilterDialog.fieldColumn', "Field");
const OperatorText: string = localize('profilerFilterDialog.operatorColumn', "Operator");
const ValueText: string = localize('profilerFilterDialog.valueColumn', "Value");
const Equals: string = '=';
const NotEquals: string = '<>';
@@ -49,18 +47,18 @@ const LessThan: string = '<';
const LessThanOrEquals: string = '<=';
const GreaterThan: string = '>';
const GreaterThanOrEquals: string = '>=';
const IsNull: string = localize('profilerFilterDialog.isNullOperator', 'Is Null');
const IsNotNull: string = localize('profilerFilterDialog.isNotNullOperator', 'Is Not Null');
const Contains: string = localize('profilerFilterDialog.containsOperator', 'Contains');
const NotContains: string = localize('profilerFilterDialog.notContainsOperator', 'Not Contains');
const StartsWith: string = localize('profilerFilterDialog.startsWithOperator', 'Starts With');
const NotStartsWith: string = localize('profilerFilterDialog.notStartsWithOperator', 'Not Starts With');
const IsNull: string = localize('profilerFilterDialog.isNullOperator', "Is Null");
const IsNotNull: string = localize('profilerFilterDialog.isNotNullOperator', "Is Not Null");
const Contains: string = localize('profilerFilterDialog.containsOperator', "Contains");
const NotContains: string = localize('profilerFilterDialog.notContainsOperator', "Not Contains");
const StartsWith: string = localize('profilerFilterDialog.startsWithOperator', "Starts With");
const NotStartsWith: string = localize('profilerFilterDialog.notStartsWithOperator', "Not Starts With");
const Operators = [Equals, NotEquals, LessThan, LessThanOrEquals, GreaterThan, GreaterThanOrEquals, GreaterThan, GreaterThanOrEquals, IsNull, IsNotNull, Contains, NotContains, StartsWith, NotStartsWith];
export class ProfilerFilterDialog extends Modal {
private _clauseBuilder: Builder;
private _clauseBuilder: HTMLElement;
private _okButton: Button;
private _cancelButton: Button;
private _clearButton: Button;
@@ -110,36 +108,27 @@ export class ProfilerFilterDialog extends Modal {
}
protected renderBody(container: HTMLElement) {
new Builder(container).div({ 'class': 'profiler-filter-dialog' }, (bodyBuilder) => {
bodyBuilder.element('table', { 'class': 'profiler-filter-clause-table' }, (builder) => {
this._clauseBuilder = builder;
});
this._clauseBuilder.element('tr', {}, (headerBuilder) => {
headerBuilder.element('td').text(FieldText);
headerBuilder.element('td').text(OperatorText);
headerBuilder.element('td').text(ValueText);
headerBuilder.element('td').text('');
});
this._input.filter.clauses.forEach(clause => {
this.addClauseRow(true, clause.field, this.convertToOperatorString(clause.operator), clause.value);
});
bodyBuilder.div({
'class': 'profiler-filter-add-clause-prompt',
'tabIndex': '0'
}).text(AddClausePromptText).on(DOM.EventType.CLICK, () => {
this.addClauseRow(false);
}).on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Space) || event.equals(KeyCode.Enter)) {
this.addClauseRow(false);
event.stopPropagation();
}
});
const body = DOM.append(container, DOM.$('.profiler-filter-dialog'));
this._clauseBuilder = DOM.append(body, DOM.$('table.profiler-filter-clause-table'));
const headerRow = DOM.append(this._clauseBuilder, DOM.$('tr'));
DOM.append(headerRow, DOM.$('td')).innerText = FieldText;
DOM.append(headerRow, DOM.$('td')).innerText = OperatorText;
DOM.append(headerRow, DOM.$('td')).innerText = ValueText;
DOM.append(headerRow, DOM.$('td')).innerText = '';
this._input.filter.clauses.forEach(clause => {
this.addClauseRow(true, clause.field, this.convertToOperatorString(clause.operator), clause.value);
});
const prompt = DOM.append(body, DOM.$('.profiler-filter-add-clause-prompt', { tabIndex: '0' }));
prompt.innerText = AddClausePromptText;
DOM.addDisposableListener(prompt, DOM.EventType.CLICK, () => this.addClauseRow(false));
DOM.addStandardDisposableListener(prompt, DOM.EventType.KEY_DOWN, (e: StandardKeyboardEvent) => {
if (e.equals(KeyCode.Space) || e.equals(KeyCode.Enter)) {
this.addClauseRow(false);
e.stopPropagation();
}
});
}
protected layout(height?: number): void {
@@ -169,7 +158,7 @@ export class ProfilerFilterDialog extends Modal {
}
private createSelectBox(container: HTMLElement, options: string[], selectedOption: string, ariaLabel: string): SelectBox {
let dropdown = new SelectBox(options, selectedOption, this.contextViewService, undefined, { ariaLabel: ariaLabel });
const dropdown = new SelectBox(options, selectedOption, this.contextViewService, undefined, { ariaLabel: ariaLabel });
dropdown.render(container);
this._register(attachSelectBoxStyler(dropdown, this._themeService));
return dropdown;
@@ -180,7 +169,7 @@ export class ProfilerFilterDialog extends Modal {
}
private getFilter(): ProfilerFilter {
let clauses: ProfilerFilterClause[] = [];
const clauses: ProfilerFilterClause[] = [];
this._clauseRows.forEach(row => {
clauses.push({
@@ -196,62 +185,52 @@ export class ProfilerFilterDialog extends Modal {
}
private addClauseRow(setInitialValue: boolean, field?: string, operator?: string, value?: string): any {
this._clauseBuilder.element('tr', {}, (rowBuilder) => {
let rowElement = rowBuilder.getHTMLElement();
let clauseId = generateUuid();
let fieldDropDown: SelectBox;
let operatorDropDown: SelectBox;
let valueText: InputBox;
const row = DOM.append(this._clauseBuilder, DOM.$('tr'));
const clauseId = generateUuid();
rowBuilder.element('td', {}, (fieldCell) => {
let columns = this._input.columns.map(column => column.name);
fieldDropDown = this.createSelectBox(fieldCell.getHTMLElement(), columns, columns[0], FieldText);
});
rowBuilder.element('td', {}, (operatorCell) => {
operatorDropDown = this.createSelectBox(operatorCell.getHTMLElement(), Operators, Operators[0], OperatorText);
});
rowBuilder.element('td', {}, (textCell) => {
valueText = new InputBox(textCell.getHTMLElement(), undefined, {});
this._register(attachInputBoxStyler(valueText, this._themeService));
});
rowBuilder.element('td', {}, (removeImageCell) => {
let removeClauseButton = removeImageCell.div({
'class': 'profiler-filter-remove-condition icon remove',
'tabIndex': '0',
'aria-label': RemoveText,
'title': RemoveText
});
const columns = this._input.columns.map(column => column.name);
const fieldDropDown = this.createSelectBox(DOM.append(row, DOM.$('td')), columns, columns[0], FieldText);
removeClauseButton.on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Space) || event.equals(KeyCode.Enter)) {
this.removeRow(clauseId);
event.stopPropagation();
}
});
const operatorDropDown = this.createSelectBox(DOM.append(row, DOM.$('td')), Operators, Operators[0], OperatorText);
removeClauseButton.on(DOM.EventType.CLICK, () => {
this.removeRow(clauseId);
});
});
const valueText = new InputBox(DOM.append(row, DOM.$('td')), undefined, {});
this._register(attachInputBoxStyler(valueText, this._themeService));
if (setInitialValue) {
fieldDropDown.selectWithOptionName(field);
operatorDropDown.selectWithOptionName(operator);
valueText.value = value;
const removeCell = DOM.append(row, DOM.$('td'));
const removeClauseButton = DOM.append(removeCell, DOM.$('.profiler-filter-remove-condition.icon.remove', {
'tabIndex': '0',
'aria-label': RemoveText,
'title': RemoveText
}));
DOM.addStandardDisposableListener(removeClauseButton, DOM.EventType.KEY_DOWN, (e: StandardKeyboardEvent) => {
if (e.equals(KeyCode.Space) || e.equals(KeyCode.Enter)) {
this.removeRow(clauseId);
e.stopPropagation();
}
this._clauseRows.push({
id: clauseId,
row: rowElement,
field: fieldDropDown,
operator: operatorDropDown,
value: valueText
});
});
DOM.addDisposableListener(removeClauseButton, DOM.EventType.CLICK, (e: MouseEvent) => {
this.removeRow(clauseId);
});
if (setInitialValue) {
fieldDropDown.selectWithOptionName(field);
operatorDropDown.selectWithOptionName(operator);
valueText.value = value;
}
this._clauseRows.push({
id: clauseId,
row,
field: fieldDropDown,
operator: operatorDropDown,
value: valueText
});
}
private removeRow(clauseId: string) {
let idx = this._clauseRows.findIndex((entry) => { return entry.id === clauseId; });
const idx = this._clauseRows.findIndex((entry) => { return entry.id === clauseId; });
if (idx !== -1) {
this._clauseRows[idx].row.remove();
this._clauseRows.splice(idx, 1);

View File

@@ -2,7 +2,6 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as pretty from 'pretty-data';
@@ -23,7 +22,6 @@ import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugi
import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin';
import { ITableStyles, ITableMouseEvent } from 'sql/base/browser/ui/table/interfaces';
import { warn } from 'sql/base/common/log';
import { $ } from 'sql/base/browser/builder';
import * as azdata from 'azdata';
@@ -203,7 +201,7 @@ export class GridPanel extends ViewletPanel {
}
}
public resetScrollPosition() : void {
public resetScrollPosition(): void {
this.splitView.setScrollPosition(this.state.scrollPosition);
}
@@ -813,7 +811,7 @@ class GridTable<T> extends Disposable implements IView {
}
public dispose() {
$(this.container).destroy();
this.container.remove();
this.table.dispose();
this.actionBar.dispose();
super.dispose();

View File

@@ -2,13 +2,12 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/messagePanel';
import { IMessagesActionContext, CopyMessagesAction, CopyAllMessagesAction } from './actions';
import QueryRunner from 'sql/platform/query/common/queryRunner';
import { QueryInput } from 'sql/parts/query/common/queryInput';
import { $ } from 'sql/base/browser/builder';
import { IExpandableTree } from 'sql/parts/objectExplorer/viewlet/treeUpdateUtils';
import { IResultMessage, ISelectionData } from 'azdata';
@@ -30,7 +29,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IExpandableTree } from 'sql/parts/objectExplorer/viewlet/treeUpdateUtils';
import { $ } from 'vs/base/browser/dom';
export interface IResultMessageIntern extends IResultMessage {
id?: string;
@@ -83,13 +82,12 @@ export class MessagePanel extends ViewletPanel {
private renderer = new MessageRenderer(this.messageLineCountMap);
private model = new Model();
private controller: MessageController;
private container = $('div message-tree').getHTMLElement();
private container = $('.message-tree');
private queryRunnerDisposables: IDisposable[] = [];
private _state: MessagePanelState;
private tree: ITree;
private _selectAllMessages: boolean;
constructor(
options: IViewletPanelOptions,
@@ -335,16 +333,22 @@ class MessageRenderer implements IRenderer {
renderTemplate(tree: ITree, templateId: string, container: HTMLElement): IMessageTemplate | IBatchTemplate {
if (templateId === TemplateIds.MESSAGE) {
$('div.time-stamp').appendTo(container);
const message = $('div.message').style('white-space', 'pre').appendTo(container).getHTMLElement();
container.append($('.time-stamp'));
const message = $('.message');
message.style.whiteSpace = 'pre';
container.append(message);
return { message };
} else if (templateId === TemplateIds.BATCH) {
const timeStamp = $('div.time-stamp').appendTo(container).getHTMLElement();
const message = $('div.batch-start').style('white-space', 'pre').appendTo(container).getHTMLElement();
const timeStamp = $('.time-stamp');
container.append(timeStamp);
const message = $('.batch-start');
message.style.whiteSpace = 'pre';
container.append(message);
return { message, timeStamp };
} else if (templateId === TemplateIds.ERROR) {
$('div.time-stamp').appendTo(container);
const message = $('div.error-message').appendTo(container).getHTMLElement();
container.append($('.time-stamp'));
const message = $('.error-message');
container.append(message);
return { message };
} else {
return undefined;

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/autoOAuthDialog';
import { Builder, $ } from 'sql/base/browser/builder';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
import { Event, Emitter } from 'vs/base/common/event';
@@ -12,6 +12,7 @@ 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';
@@ -82,37 +83,21 @@ export class AutoOAuthDialog extends Modal {
}
protected renderBody(container: HTMLElement) {
$().div({ class: 'auto-oauth-description-section new-section' }, (descriptionContainer) => {
this._descriptionElement = descriptionContainer.getHTMLElement();
});
this._descriptionElement = append(container, $('.auto-oauth-description-section.new-section'));
let addAccountSection;
$().div({ class: 'auto-oauth-info-section new-section' }, (addAccountContainer) => {
addAccountSection = addAccountContainer.getHTMLElement();
this._userCodeInputBox = this.createInputBoxHelper(addAccountContainer, localize('userCode', 'User code'));
this._websiteInputBox = this.createInputBoxHelper(addAccountContainer, localize('website', 'Website'));
});
new Builder(container).div({ class: 'auto-oauth-dialog' }, (builder) => {
builder.append(this._descriptionElement);
builder.append(addAccountSection);
});
const addAccountSection = append(container, $('.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: Builder, label: string): InputBox {
let inputBox: InputBox;
container.div({ class: 'dialog-input-section' }, (inputContainer) => {
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => {
labelContainer.text(label);
});
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'));
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => {
inputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, {
ariaLabel: label
});
});
return new InputBox(inputCellContainer, this._contextViewService, {
ariaLabel: label
});
return inputBox;
}
private registerListeners(): void {

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/firewallRuleDialog';
import { Builder, $ } from 'sql/base/browser/builder';
import * as DOM from 'vs/base/browser/dom';
import { Event, Emitter } from 'vs/base/common/event';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
@@ -18,6 +18,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IWindowsService } from 'vs/platform/windows/common/windows';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
import * as azdata from 'azdata';
import { Button } from 'sql/base/browser/ui/button/button';
@@ -27,15 +28,14 @@ import { attachModalDialogStyler, attachButtonStyler } from 'sql/platform/theme/
import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
import { IAccountPickerService } from 'sql/platform/accounts/common/accountPicker';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
// 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')
FROM: localize('from', "From"),
TO: localize('to', "To")
};
export class FirewallRuleDialog extends Modal {
@@ -62,7 +62,7 @@ export class FirewallRuleDialog extends Modal {
constructor(
@IAccountPickerService private _accountPickerService: IAccountPickerService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@ILayoutService layoutService: ILayoutService,
@IThemeService themeService: IThemeService,
@IInstantiationService private _instantiationService: IInstantiationService,
@IContextViewService private _contextViewService: IContextViewService,
@@ -72,7 +72,7 @@ export class FirewallRuleDialog extends Modal {
@IClipboardService clipboardService: IClipboardService
) {
super(
localize('createNewFirewallRule', 'Create new firewall rule'),
localize('createNewFirewallRule', "Create new firewall rule"),
TelemetryKeys.FireWallRule,
telemetryService,
layoutService,
@@ -99,29 +99,28 @@ export class FirewallRuleDialog extends Modal {
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._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) {
let descriptionSection;
$().div({ 'class': 'firewall-rule-description-section new-section' }, (descriptionContainer) => {
descriptionSection = descriptionContainer.getHTMLElement();
DOM.append(descriptionContainer.getHTMLElement(), DOM.$('div.firewall-rule-icon'));
const body = DOM.append(container, DOM.$('.firewall-rule-dialog'));
const descriptionSection = DOM.append(body, DOM.$('.firewall-rule-description-section.new-section'));
const textDescriptionContainer = DOM.append(descriptionContainer.getHTMLElement(), DOM.$('div.firewall-rule-description'));
let 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(new Builder(textDescriptionContainer), dialogDescription, false);
DOM.append(descriptionSection, DOM.$('div.firewall-rule-icon'));
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._windowsService.openExternal(firewallHelpUri);
};
});
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._windowsService.openExternal(firewallHelpUri);
};
// Create account picker with event handling
this._accountPickerService.addAccountCompleteEvent(() => this.spinner = false);
@@ -132,88 +131,61 @@ export class FirewallRuleDialog extends Modal {
this._accountPickerService.addAccountStartEvent(() => this.spinner = true);
this._accountPickerService.onAccountSelectionChangeEvent((account) => this.onAccountSelectionChange(account));
let azureAccountSection;
$().div({ 'class': 'azure-account-section new-section' }, (azureAccountContainer) => {
azureAccountSection = azureAccountContainer.getHTMLElement();
let azureAccountLabel = localize('azureAccount', 'Azure account');
this.createLabelElement(azureAccountContainer, azureAccountLabel, true);
azureAccountContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => {
this._accountPickerService.renderAccountPicker(inputCellContainer.getHTMLElement());
});
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
});
let subnetIPRangeSection;
$().div({ 'class': 'subnet-ip-range-input' }, (subnetIPRangeContainer) => {
subnetIPRangeSection = subnetIPRangeContainer.getHTMLElement();
subnetIPRangeContainer.div({ 'class': 'dialog-input-section' }, (inputContainer) => {
inputContainer.div({ 'class': 'dialog-label' }, (labelContainer) => {
labelContainer.text(LocalizedStrings.FROM);
});
DOM.append(inputContainer, DOM.$('.dialog-label')).innerText = LocalizedStrings.TO;
inputContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => {
this._fromRangeinputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, {
ariaLabel: LocalizedStrings.FROM
});
});
inputContainer.div({ 'class': 'dialog-label' }, (labelContainer) => {
labelContainer.text(LocalizedStrings.TO);
});
inputContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => {
this._toRangeinputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, {
ariaLabel: LocalizedStrings.TO
});
});
});
});
let firewallRuleSection;
$().div({ 'class': 'firewall-rule-section new-section' }, (firewallRuleContainer) => {
firewallRuleSection = firewallRuleContainer.getHTMLElement();
const firewallRuleLabel = localize('filewallRule', 'Firewall rule');
this.createLabelElement(firewallRuleContainer, firewallRuleLabel, true);
firewallRuleContainer.div({ 'class': 'radio-section' }, (radioContainer) => {
const form = DOM.append(radioContainer.getHTMLElement(), DOM.$('form.firewall-rule'));
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');
DOM.append(subnetIPRangeDiv, subnetIPRangeSection);
});
});
new Builder(container).div({ 'class': 'firewall-rule-dialog' }, (builder) => {
builder.append(descriptionSection);
builder.append(azureAccountSection);
builder.append(firewallRuleSection);
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._IPAddressInput).on(DOM.EventType.CLICK, () => {
this._register(DOM.addDisposableListener(this._IPAddressElement, DOM.EventType.CLICK, () => {
this.onFirewallRuleOptionSelected(true);
});
}));
$(this._subnetIPRangeInput).on(DOM.EventType.CLICK, () => {
this._register(DOM.addDisposableListener(this._subnetIPRangeInput, DOM.EventType.CLICK, () => {
this.onFirewallRuleOptionSelected(false);
});
}));
}
private onFirewallRuleOptionSelected(isIPAddress: boolean) {
@@ -230,14 +202,12 @@ export class FirewallRuleDialog extends Modal {
// Nothing currently laid out statically in this class
}
private createLabelElement(container: Builder, content: string, isHeader?: boolean) {
private createLabelElement(container: HTMLElement, content: string, isHeader?: boolean) {
let className = 'dialog-label';
if (isHeader) {
className += ' header';
}
container.div({ 'class': className }, (labelContainer) => {
labelContainer.text(content);
});
DOM.append(container, DOM.$(`.${className}`)).innerText = content;
}
// Update theming that is specific to firewall rule flyout body

View File

@@ -23,7 +23,6 @@ import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { $ } from 'sql/base/browser/builder';
export class DashboardEditor extends BaseEditor {
@@ -85,7 +84,7 @@ export class DashboardEditor extends BaseEditor {
super.setInput(input, options, CancellationToken.None);
$(parentElement).clearChildren();
DOM.clearNode(parentElement);
if (!input.hasBootstrapped) {
const container = DOM.$<HTMLElement>('.dashboardEditor');

View File

@@ -16,7 +16,6 @@ import { NotebookModule } from 'sql/workbench/parts/notebook/notebook.module';
import { NOTEBOOK_SELECTOR } from 'sql/workbench/parts/notebook/notebook.component';
import { INotebookParams } from 'sql/workbench/services/notebook/common/notebookService';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { $ } from 'sql/base/browser/builder';
export class NotebookEditor extends BaseEditor {
@@ -67,7 +66,7 @@ export class NotebookEditor extends BaseEditor {
super.setInput(input, options, CancellationToken.None);
$(parentElement).clearChildren();
DOM.clearNode(parentElement);
if (!input.hasBootstrapped) {
let container = DOM.$<HTMLElement>('.notebookEditor');
@@ -104,4 +103,3 @@ export class NotebookEditor extends BaseEditor {
);
}
}

View File

@@ -21,10 +21,8 @@ import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { ClearRecentConnectionsAction } from 'sql/parts/connection/common/connectionActions';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IWorkbenchThemeService, IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { Event, Emitter } from 'vs/base/common/event';
import { Builder, $ } from 'sql/base/browser/builder';
import { ICancelableEvent } from 'vs/base/parts/tree/browser/treeDefaults';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -37,7 +35,8 @@ import * as DOM from 'vs/base/browser/dom';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
export interface OnShowUIResponse {
selectedProviderType: string;
@@ -45,19 +44,19 @@ export interface OnShowUIResponse {
}
export class ConnectionDialogWidget extends Modal {
private _bodyBuilder: Builder;
private _recentConnectionBuilder: Builder;
private _noRecentConnectionBuilder: Builder;
private _savedConnectionBuilder: Builder;
private _noSavedConnectionBuilder: Builder;
private _connectionDetailTitle: Builder;
private _body: HTMLElement;
private _recentConnection: HTMLElement;
private _noRecentConnection: HTMLElement;
private _savedConnection: HTMLElement;
private _noSavedConnection: HTMLElement;
private _connectionDetailTitle: HTMLElement;
private _connectButton: Button;
private _closeButton: Button;
private _providerTypeSelectBox: SelectBox;
private _newConnectionParams: INewConnectionParams;
private _recentConnectionTree: ITree;
private _savedConnectionTree: ITree;
private $connectionUIContainer: Builder;
private _connectionUIContainer: HTMLElement;
private _databaseDropdownExpanded: boolean;
private _actionbar: ActionBar;
private _providers: string[];
@@ -91,15 +90,15 @@ export class ConnectionDialogWidget extends Modal {
private providerNameToDisplayNameMap: { [providerDisplayName: string]: string },
@IInstantiationService private _instantiationService: IInstantiationService,
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@IWorkbenchThemeService private _workbenchThemeService: IWorkbenchThemeService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IThemeService themeService: IThemeService,
@ILayoutService layoutService: ILayoutService,
@ITelemetryService telemetryService: ITelemetryService,
@IContextKeyService contextKeyService: IContextKeyService,
@IContextMenuService private _contextMenuService: IContextMenuService,
@IContextViewService private _contextViewService: IContextViewService,
@IClipboardService clipboardService: IClipboardService
) {
super(localize('connection', 'Connection'), TelemetryKeys.Connection, telemetryService, layoutService, clipboardService, _workbenchThemeService, contextKeyService, { hasSpinner: true, hasErrors: true });
super(localize('connection', "Connection"), TelemetryKeys.Connection, telemetryService, layoutService, clipboardService, themeService, contextKeyService, { hasSpinner: true, hasErrors: true });
}
/**
@@ -117,7 +116,7 @@ export class ConnectionDialogWidget extends Modal {
let filteredProviderTypes = this.providerTypeOptions;
if (this._newConnectionParams && this._newConnectionParams.providers) {
let validProviderNames = Object.keys(this.providerNameToDisplayNameMap).filter(x => this.includeProvider(x, this._newConnectionParams));
const validProviderNames = Object.keys(this.providerNameToDisplayNameMap).filter(x => this.includeProvider(x, this._newConnectionParams));
if (validProviderNames && validProviderNames.length > 0) {
filteredProviderTypes = filteredProviderTypes.filter(x => validProviderNames.find(v => this.providerNameToDisplayNameMap[v] === x) !== undefined);
}
@@ -130,90 +129,84 @@ export class ConnectionDialogWidget extends Modal {
}
protected renderBody(container: HTMLElement): void {
let connectionContainer = $('.connection-dialog');
container.appendChild(connectionContainer.getHTMLElement());
this._body = DOM.append(container, DOM.$('.connection-dialog'));
this._bodyBuilder = new Builder(connectionContainer.getHTMLElement());
const connectTypeLabel = localize('connectType', 'Connection type');
const connectTypeLabel = localize('connectType', "Connection type");
this._providerTypeSelectBox = new SelectBox(this.providerTypeOptions, this.selectedProviderType, this._contextViewService, undefined, { ariaLabel: connectTypeLabel });
// Recent connection tab
let recentConnectionTab = $('.connection-recent-tab');
recentConnectionTab.div({ class: 'connection-recent', id: 'recentConnection' }, (builder) => {
this._recentConnectionBuilder = new Builder(builder.getHTMLElement());
this._noRecentConnectionBuilder = new Builder(builder.getHTMLElement());
this.createRecentConnections();
this._recentConnectionBuilder.hide();
});
const recentConnectionTab = DOM.$('.connection-recent-tab');
const recentConnectionContainer = DOM.append(recentConnectionTab, DOM.$('.connection-recent', { id: 'recentConnection' }));
this._recentConnection = DOM.append(recentConnectionContainer, DOM.$('div'));
this._recentConnection.style.height = '100%';
this._noRecentConnection = DOM.append(recentConnectionContainer, DOM.$('div'));
this.createRecentConnections();
DOM.hide(this._recentConnection);
// Saved connection tab
let savedConnectionTab = $('.connection-saved-tab');
savedConnectionTab.div({ class: 'connection-saved' }, (builder) => {
this._savedConnectionBuilder = new Builder(builder.getHTMLElement());
this._noSavedConnectionBuilder = new Builder(builder.getHTMLElement());
this.createSavedConnections();
this._savedConnectionBuilder.hide();
});
const savedConnectionTab = DOM.$('.connection-saved-tab');
const savedConnectionContainer = DOM.append(savedConnectionTab, DOM.$('.connection-saved'));
this._savedConnection = DOM.append(savedConnectionContainer, DOM.$('div'));
this._savedConnection.style.height = '100%';
this._noSavedConnection = DOM.append(savedConnectionContainer, DOM.$('div'));
this.createSavedConnections();
DOM.hide(this._savedConnection);
this._panel = new TabbedPanel(connectionContainer.getHTMLElement());
this._panel = new TabbedPanel(this._body);
this._recentConnectionTabId = this._panel.pushTab({
identifier: 'recent_connection',
title: localize('recentConnectionTitle', 'Recent Connections'),
title: localize('recentConnectionTitle', "Recent Connections"),
view: {
render: c => {
recentConnectionTab.appendTo(c);
c.append(recentConnectionTab);
},
layout: () => { }
}
});
let savedConnectionTabId = this._panel.pushTab({
const savedConnectionTabId = this._panel.pushTab({
identifier: 'saved_connection',
title: localize('savedConnectionTitle', 'Saved Connections'),
title: localize('savedConnectionTitle', "Saved Connections"),
view: {
layout: () => { },
render: c => {
savedConnectionTab.appendTo(c);
c.append(savedConnectionTab);
}
}
});
this._panel.onTabChange(async c => {
// convert to old VS Code tree interface with expandable methods
let expandableTree: IExpandableTree = <IExpandableTree>this._savedConnectionTree;
const expandableTree: IExpandableTree = <IExpandableTree>this._savedConnectionTree;
if (c === savedConnectionTabId && expandableTree.getContentHeight() === 0) {
// Update saved connection tree
await TreeUpdateUtils.structuralTreeUpdate(this._savedConnectionTree, 'saved', this._connectionManagementService, this._providers);
if (expandableTree.getContentHeight() > 0) {
this._noSavedConnectionBuilder.hide();
this._savedConnectionBuilder.show();
DOM.hide(this._noSavedConnection);
DOM.show(this._savedConnection);
} else {
this._noSavedConnectionBuilder.show();
this._savedConnectionBuilder.hide();
DOM.show(this._noSavedConnection);
DOM.hide(this._savedConnection);
}
this._savedConnectionTree.layout(DOM.getTotalHeight(this._savedConnectionTree.getHTMLElement()));
}
});
this._bodyBuilder.div({ class: 'connection-details-title' }, (dividerContainer) => {
this._connectionDetailTitle = dividerContainer;
this._connectionDetailTitle.text(localize('connectionDetailsTitle', 'Connection Details'));
});
this._connectionDetailTitle = DOM.append(this._body, DOM.$('.connection-details-title'));
this._bodyBuilder.div({ class: 'connection-type' }, (modelTableContent) => {
modelTableContent.element('table', { class: 'connection-table-content' }, (tableContainer) => {
DialogHelper.appendInputSelectBox(
DialogHelper.appendRow(tableContainer.getHTMLElement(), connectTypeLabel, 'connection-label', 'connection-input'), this._providerTypeSelectBox);
});
});
this._connectionDetailTitle.innerText = localize('connectionDetailsTitle', "Connection Details");
this.$connectionUIContainer = $('.connection-provider-info#connectionProviderInfo');
this.$connectionUIContainer.appendTo(this._bodyBuilder);
const tableContainer = DOM.append(this._body, DOM.$('.connection-type'));
const table = DOM.append(tableContainer, DOM.$('table.connection-table-content'));
DialogHelper.appendInputSelectBox(
DialogHelper.appendRow(table, connectTypeLabel, 'connection-label', 'connection-input'), this._providerTypeSelectBox);
let self = this;
this._register(self._workbenchThemeService.onDidColorThemeChange(e => self.updateTheme(e)));
self.updateTheme(self._workbenchThemeService.getColorTheme());
this._connectionUIContainer = DOM.$('.connection-provider-info', { id: 'connectionProviderInfo' });
this._body.append(this._connectionUIContainer);
this._register(this._themeService.onThemeChange(e => this.updateTheme(e)));
this.updateTheme(this._themeService.getTheme());
}
/**
@@ -222,8 +215,8 @@ export class ConnectionDialogWidget extends Modal {
public render() {
super.render();
attachModalDialogStyler(this, this._themeService);
let connectLabel = localize('connectionDialog.connect', 'Connect');
let cancelLabel = localize('connectionDialog.cancel', 'Cancel');
const connectLabel = localize('connectionDialog.connect', "Connect");
const cancelLabel = localize('connectionDialog.cancel', "Cancel");
this._connectButton = this.addFooterButton(connectLabel, () => this.connect());
this._connectButton.enabled = false;
this._closeButton = this.addFooterButton(cancelLabel, () => this.cancel());
@@ -232,15 +225,15 @@ export class ConnectionDialogWidget extends Modal {
}
// Update theming that is specific to connection flyout body
private updateTheme(theme: IColorTheme): void {
let borderColor = theme.getColor(contrastBorder);
let border = borderColor ? borderColor.toString() : null;
let backgroundColor = theme.getColor(SIDE_BAR_BACKGROUND);
private updateTheme(theme: ITheme): void {
const borderColor = theme.getColor(contrastBorder);
const border = borderColor ? borderColor.toString() : null;
const backgroundColor = theme.getColor(SIDE_BAR_BACKGROUND);
if (this._connectionDetailTitle) {
this._connectionDetailTitle.style('border-width', border ? '1px 0px' : null);
this._connectionDetailTitle.style('border-style', border ? 'solid none' : null);
this._connectionDetailTitle.style('border-color', border);
this._connectionDetailTitle.style('background-color', backgroundColor ? backgroundColor.toString() : null);
this._connectionDetailTitle.style.borderWidth = border ? '1px 0px' : null;
this._connectionDetailTitle.style.borderStyle = border ? 'solid none' : null;
this._connectionDetailTitle.style.borderColor = border;
this._connectionDetailTitle.style.backgroundColor = backgroundColor ? backgroundColor.toString() : null;
}
}
@@ -257,8 +250,8 @@ export class ConnectionDialogWidget extends Modal {
private onProviderTypeSelected(selectedProviderType: string) {
// Show connection form based on server type
this.$connectionUIContainer.empty();
this._onShowUiComponent.fire({ selectedProviderType: selectedProviderType, container: this.$connectionUIContainer.getHTMLElement() });
DOM.clearNode(this._connectionUIContainer);
this._onShowUiComponent.fire({ selectedProviderType: selectedProviderType, container: this._connectionUIContainer });
this.initDialog();
}
@@ -285,7 +278,7 @@ export class ConnectionDialogWidget extends Modal {
}
private cancel() {
let wasConnecting = this._connecting;
const wasConnecting = this._connecting;
this._onCancel.fire();
if (!this._databaseDropdownExpanded && !wasConnecting) {
this.close();
@@ -298,87 +291,71 @@ export class ConnectionDialogWidget extends Modal {
}
private createRecentConnectionList(): void {
this._recentConnectionBuilder.div({ class: 'connection-recent-content' }, (recentConnectionContainer) => {
recentConnectionContainer.div({ class: 'recent-titles-container' }, (container) => {
container.div({ class: 'connection-history-actions' }, (actionsContainer) => {
this._actionbar = this._register(new ActionBar(actionsContainer.getHTMLElement(), { animated: false }));
let clearAction = this._instantiationService.createInstance(ClearRecentConnectionsAction, ClearRecentConnectionsAction.ID, ClearRecentConnectionsAction.LABEL);
clearAction.useConfirmationMessage = true;
clearAction.onRecentConnectionsRemoved(() => this.open(false));
this._actionbar.push(clearAction, { icon: true, label: true });
});
});
recentConnectionContainer.div({ class: 'server-explorer-viewlet' }, (divContainer: Builder) => {
divContainer.div({ class: 'explorer-servers' }, (treeContainer: Builder) => {
let leftClick = (element: any, eventish: ICancelableEvent, origin: string) => {
// element will be a server group if the tree is clicked rather than a item
if (element instanceof ConnectionProfile) {
this.onConnectionClick({ payload: { origin: origin, originalEvent: eventish } }, element);
}
};
let actionProvider = this._instantiationService.createInstance(RecentConnectionActionsProvider);
let controller = new RecentConnectionTreeController(leftClick, actionProvider, this._connectionManagementService, this._contextMenuService);
actionProvider.onRecentConnectionRemoved(() => {
this.open(this._connectionManagementService.getRecentConnections().length > 0);
});
controller.onRecentConnectionRemoved(() => {
this.open(this._connectionManagementService.getRecentConnections().length > 0);
});
this._recentConnectionTree = TreeCreationUtils.createConnectionTree(treeContainer.getHTMLElement(), this._instantiationService, controller);
// Theme styler
this._register(styler.attachListStyler(this._recentConnectionTree, this._themeService));
divContainer.append(this._recentConnectionTree.getHTMLElement());
});
});
const recentConnectionContainer = DOM.append(this._recentConnection, DOM.$('.connection-recent-content'));
const container = DOM.append(recentConnectionContainer, DOM.$('.recent-titles-container'));
const actionsContainer = DOM.append(container, DOM.$('.connection-history-actions'));
this._actionbar = this._register(new ActionBar(actionsContainer, { animated: false }));
const clearAction = this._instantiationService.createInstance(ClearRecentConnectionsAction, ClearRecentConnectionsAction.ID, ClearRecentConnectionsAction.LABEL);
clearAction.useConfirmationMessage = true;
clearAction.onRecentConnectionsRemoved(() => this.open(false));
this._actionbar.push(clearAction, { icon: true, label: true });
const divContainer = DOM.append(recentConnectionContainer, DOM.$('.server-explorer-viewlet'));
const treeContainer = DOM.append(divContainer, DOM.$('.explorer-servers'));
const leftClick = (element: any, eventish: ICancelableEvent, origin: string) => {
// element will be a server group if the tree is clicked rather than a item
if (element instanceof ConnectionProfile) {
this.onConnectionClick({ payload: { origin: origin, originalEvent: eventish } }, element);
}
};
const actionProvider = this._instantiationService.createInstance(RecentConnectionActionsProvider);
const controller = new RecentConnectionTreeController(leftClick, actionProvider, this._connectionManagementService, this._contextMenuService);
actionProvider.onRecentConnectionRemoved(() => {
this.open(this._connectionManagementService.getRecentConnections().length > 0);
});
controller.onRecentConnectionRemoved(() => {
this.open(this._connectionManagementService.getRecentConnections().length > 0);
});
this._recentConnectionTree = TreeCreationUtils.createConnectionTree(treeContainer, this._instantiationService, controller);
// Theme styler
this._register(styler.attachListStyler(this._recentConnectionTree, this._themeService));
}
private createRecentConnections() {
this.createRecentConnectionList();
this._noRecentConnectionBuilder.div({ class: 'connection-recent-content' }, (noRecentConnectionContainer) => {
let noRecentHistoryLabel = localize('noRecentConnections', 'No recent connection');
noRecentConnectionContainer.div({ class: 'no-recent-connections' }, (noRecentTitle) => {
noRecentTitle.text(noRecentHistoryLabel);
});
});
const noRecentConnectionContainer = DOM.append(this._noRecentConnection, DOM.$('.connection-recent-content'));
const noRecentHistoryLabel = localize('noRecentConnections', "No recent connection");
DOM.append(noRecentConnectionContainer, DOM.$('.no-recent-connections')).innerText = noRecentHistoryLabel;
}
private createSavedConnectionList(): void {
this._savedConnectionBuilder.div({ class: 'connection-saved-content' }, (savedConnectioncontainer) => {
savedConnectioncontainer.div({ class: 'server-explorer-viewlet' }, (divContainer: Builder) => {
divContainer.div({ class: 'explorer-servers' }, (treeContainer: Builder) => {
let leftClick = (element: any, eventish: ICancelableEvent, origin: string) => {
// element will be a server group if the tree is clicked rather than a item
if (element instanceof ConnectionProfile) {
this.onConnectionClick({ payload: { origin: origin, originalEvent: eventish } }, element);
}
};
const savedConnectioncontainer = DOM.append(this._savedConnection, DOM.$('.connection-saved-content'));
const divContainer = DOM.append(savedConnectioncontainer, DOM.$('.server-explorer-viewlet'));
const treeContainer = DOM.append(divContainer, DOM.$('.explorer-servers'));
const leftClick = (element: any, eventish: ICancelableEvent, origin: string) => {
// element will be a server group if the tree is clicked rather than a item
if (element instanceof ConnectionProfile) {
this.onConnectionClick({ payload: { origin: origin, originalEvent: eventish } }, element);
}
};
let controller = new SavedConnectionTreeController(leftClick);
this._savedConnectionTree = TreeCreationUtils.createConnectionTree(treeContainer.getHTMLElement(), this._instantiationService, controller);
const controller = new SavedConnectionTreeController(leftClick);
this._savedConnectionTree = TreeCreationUtils.createConnectionTree(treeContainer, this._instantiationService, controller);
// Theme styler
this._register(styler.attachListStyler(this._savedConnectionTree, this._themeService));
divContainer.append(this._savedConnectionTree.getHTMLElement());
});
});
});
// Theme styler
this._register(styler.attachListStyler(this._savedConnectionTree, this._themeService));
}
private createSavedConnections() {
this.createSavedConnectionList();
this._noSavedConnectionBuilder.div({ class: 'connection-saved-content' }, (noSavedConnectionContainer) => {
let noSavedConnectionLabel = localize('noSavedConnections', 'No saved connection');
noSavedConnectionContainer.div({ class: 'no-saved-connections' }, (titleContainer) => {
titleContainer.text(noSavedConnectionLabel);
});
});
const noSavedConnectionContainer = DOM.append(this._noSavedConnection, DOM.$('.connection-saved-content'));
const noSavedConnectionLabel = localize('noSavedConnections', "No saved connection");
DOM.append(noSavedConnectionContainer, DOM.$('.no-saved-connections')).innerText = noSavedConnectionLabel;
}
private onConnectionClick(event: any, element: IConnectionProfile) {
let isMouseOrigin = event.payload && (event.payload.origin === 'mouse');
let isDoubleClick = isMouseOrigin && event.payload.originalEvent && event.payload.originalEvent.detail === 2;
const isMouseOrigin = event.payload && (event.payload.origin === 'mouse');
const isDoubleClick = isMouseOrigin && event.payload.originalEvent && event.payload.originalEvent.detail === 2;
if (isDoubleClick) {
this.connect(element);
} else {
@@ -397,11 +374,11 @@ export class ConnectionDialogWidget extends Modal {
this.show();
if (recentConnections) {
this._noRecentConnectionBuilder.hide();
this._recentConnectionBuilder.show();
DOM.hide(this._noRecentConnection);
DOM.show(this._recentConnection);
} else {
this._recentConnectionBuilder.hide();
this._noRecentConnectionBuilder.show();
DOM.hide(this._recentConnection);
DOM.show(this._noRecentConnection);
}
await TreeUpdateUtils.structuralTreeUpdate(this._recentConnectionTree, 'recent', this._connectionManagementService, this._providers);

View File

@@ -90,6 +90,22 @@
margin: 0px 13px;
}
.connection-recent-tab {
height: 100%;
}
.connection-recent {
height: 100%;
}
.connection-saved-tab {
height: 100%;
}
.connection-saved {
height: 100%;
}
.vs-dark .connection-dialog .connection-history-actions .action-label.icon,
.hc-black .connection-dialog .connection-history-actions .action-label.icon,
.connection-dialog .connection-history-actions .action-label.icon {