mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-07 09:35:41 -05:00
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:
File diff suppressed because it is too large
Load Diff
@@ -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';
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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 {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user