add strict compile for restore (#12067)

This commit is contained in:
Anthony Dresser
2020-09-02 11:58:30 -07:00
committed by GitHub
parent bfe694763b
commit 8b8bef0401
9 changed files with 214 additions and 230 deletions

View File

@@ -49,8 +49,8 @@ export function getBooleanValueFromStringOrBoolean(value: any): boolean {
return false;
}
export function getCategoryDisplayName(categories: azdata.CategoryValue[], categoryName: string) {
let displayName: string;
export function getCategoryDisplayName(categories: azdata.CategoryValue[], categoryName: string): string | undefined {
let displayName: string | undefined;
categories.forEach(c => {
if (c.name === categoryName) {
displayName = c.displayName;
@@ -59,8 +59,8 @@ export function getCategoryDisplayName(categories: azdata.CategoryValue[], categ
return displayName;
}
export function getCategoryName(categories: azdata.CategoryValue[], categoryDisplayName: string) {
let categoryName: string;
export function getCategoryName(categories: azdata.CategoryValue[], categoryDisplayName: string): string | undefined {
let categoryName: string | undefined;
categories.forEach(c => {
if (c.displayName === categoryDisplayName) {
categoryName = c.name;

View File

@@ -36,14 +36,14 @@ export interface IOptionsDialogOptions extends IModalOptions {
}
export class OptionsDialog extends Modal {
private _body: HTMLElement;
private _optionGroupsContainer: HTMLElement;
private _body?: HTMLElement;
private _optionGroupsContainer?: HTMLElement;
private _categoryTitles: HTMLElement[] = [];
private _dividerBuilder: HTMLElement;
private _optionTitle: HTMLElement;
private _optionDescription: HTMLElement;
private _dividerBuilder?: HTMLElement;
private _optionTitle?: HTMLElement;
private _optionDescription?: HTMLElement;
private _optionElements: { [optionName: string]: OptionsDialogHelper.IOptionElement } = {};
private _optionValues: { [optionName: string]: string };
private _optionValues: { [optionName: string]: string } = {};
private _onOk = new Emitter<void>();
public onOk: Event<void> = this._onOk.event;
@@ -54,7 +54,7 @@ export class OptionsDialog extends Modal {
constructor(
title: string,
name: string,
options: IOptionsDialogOptions,
options: IOptionsDialogOptions | undefined,
@ILayoutService layoutService: ILayoutService,
@IThemeService themeService: IThemeService,
@IContextViewService private _contextViewService: IContextViewService,
@@ -99,25 +99,25 @@ export class OptionsDialog extends Modal {
// Update theming that is specific to options dialog flyout body
private updateTheme(theme: IColorTheme): void {
const borderColor = theme.getColor(contrastBorder);
const border = borderColor ? borderColor.toString() : null;
const border = borderColor ? borderColor.toString() : '';
const backgroundColor = theme.getColor(SIDE_BAR_BACKGROUND);
if (this._dividerBuilder) {
this._dividerBuilder.style.borderTopWidth = border ? '1px' : null;
this._dividerBuilder.style.borderTopStyle = border ? 'solid' : null;
this._dividerBuilder.style.borderTopWidth = border ? '1px' : '';
this._dividerBuilder.style.borderTopStyle = border ? 'solid' : '';
this._dividerBuilder.style.borderTopColor = border;
}
this._categoryTitles.forEach(titleElement => {
titleElement.style.borderWidth = border ? '1px 0px' : null;
titleElement.style.borderStyle = border ? 'solid none' : null;
titleElement.style.borderWidth = border ? '1px 0px' : '';
titleElement.style.borderStyle = border ? 'solid none' : '';
titleElement.style.borderColor = border;
titleElement.style.backgroundColor = backgroundColor ? backgroundColor.toString() : null;
titleElement.style.backgroundColor = backgroundColor ? backgroundColor.toString() : '';
});
}
private onOptionLinkClicked(optionName: string): void {
let option = this._optionElements[optionName].option;
this._optionTitle.innerText = option.displayName;
this._optionDescription.innerText = option.description;
this._optionTitle!.innerText = option.displayName;
this._optionDescription!.innerText = option.description;
}
private fillInOptions(container: HTMLElement, options: azdata.ServiceOption[]): void {
@@ -193,18 +193,18 @@ export class OptionsDialog extends Modal {
public open(options: azdata.ServiceOption[], optionValues: { [name: string]: any }) {
this._optionValues = optionValues;
let firstOption: string;
let firstOption: string | undefined;
let categoryMap = OptionsDialogHelper.groupOptionsByCategory(options);
clearNode(this._optionGroupsContainer);
clearNode(this._optionGroupsContainer!);
for (let category in categoryMap) {
const title = append(this._optionGroupsContainer, $('h2.option-category-title'));
const title = append(this._optionGroupsContainer!, $('h2.option-category-title'));
title.innerText = category;
this._categoryTitles.push(title);
let serviceOptions: azdata.ServiceOption[] = categoryMap[category];
let bodyContainer = $('table.optionsDialog-table');
this.fillInOptions(bodyContainer, serviceOptions);
append(this._optionGroupsContainer, bodyContainer);
append(this._optionGroupsContainer!, bodyContainer);
if (!firstOption) {
firstOption = serviceOptions[0].name;
@@ -212,7 +212,7 @@ export class OptionsDialog extends Modal {
}
this.updateTheme(this._themeService.getColorTheme());
this.show();
let firstOptionWidget = this._optionElements[firstOption].optionWidget;
let firstOptionWidget = this._optionElements[firstOption!].optionWidget;
this.registerStyling();
setTimeout(() => firstOptionWidget.focus(), 1);
}

View File

@@ -11,7 +11,6 @@ import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
import * as types from 'vs/base/common/types';
import * as azdata from 'azdata';
import { localize } from 'vs/nls';
import { startsWith } from 'vs/base/common/strings';
import { ServiceOptionType } from 'sql/platform/connection/common/interfaces';
export interface IOptionElement {
@@ -21,11 +20,11 @@ export interface IOptionElement {
}
export function createOptionElement(option: azdata.ServiceOption, rowContainer: HTMLElement, options: { [name: string]: any },
optionsMap: { [optionName: string]: IOptionElement }, contextViewService: IContextViewService, onFocus: (name) => void): IOptionElement {
optionsMap: { [optionName: string]: IOptionElement }, contextViewService: IContextViewService, onFocus: (name: string) => void): IOptionElement {
let possibleInputs: SelectOptionItemSQL[] = [];
let optionValue = getOptionValueAndCategoryValues(option, options, possibleInputs);
let optionWidget: any;
let inputElement: HTMLElement;
let inputElement: HTMLElement | undefined;
let missingErrorMessage = localize('optionsDialog.missingRequireField', " is required.");
let invalidInputMessage = localize('optionsDialog.invalidInput', "Invalid input. Numeric value expected.");
@@ -65,7 +64,9 @@ export function createOptionElement(option: azdata.ServiceOption, rowContainer:
}
const optionElement = { optionWidget: optionWidget, option: option, optionValue: optionValue };
optionsMap[option.name] = optionElement;
inputElement.onfocus = () => onFocus(option.name);
if (inputElement) {
inputElement.onfocus = () => onFocus(option.name);
}
return optionElement;
}
@@ -153,7 +154,7 @@ export function findElement(container: HTMLElement, className: string): HTMLElem
let elementBuilder = container;
while (elementBuilder) {
let htmlElement = elementBuilder;
if (startsWith(htmlElement.className, className)) {
if (htmlElement.className.startsWith(className)) {
break;
}
elementBuilder = elementBuilder.firstChild as HTMLElement;

View File

@@ -61,27 +61,27 @@ const LocalizedStrings = {
export class RestoreDialog extends Modal {
public viewModel: RestoreViewModel;
private _scriptButton: Button;
private _restoreButton: Button;
private _closeButton: Button;
private _scriptButton?: Button;
private _restoreButton?: Button;
private _closeButton?: Button;
private _optionsMap: { [name: string]: SelectBox | InputBox | Checkbox } = {};
private _restoreLabel: string;
private _restoreTitle: string;
private _databaseTitle: string;
private _backupFileTitle: string;
private _ownerUri: string;
private _databaseDropdown: Dropdown;
private _isBackupFileCheckboxChanged: boolean;
private _restoreLabel = localize('restoreDialog.restore', "Restore");
private _restoreTitle = localize('restoreDialog.restoreTitle', "Restore database");
private _databaseTitle = localize('restoreDialog.database', "Database");
private _backupFileTitle = localize('restoreDialog.backupFile', "Backup file");
private _ownerUri?: string;
private _databaseDropdown?: Dropdown;
private _isBackupFileCheckboxChanged?: boolean;
// General options
private _filePathInputBox: InputBox;
private _browseFileButton: Button;
private _destinationRestoreToInputBox: InputBox;
private _restoreFromSelectBox: SelectBox;
private _sourceDatabaseSelectBox: SelectBox;
private _filePathInputBox?: InputBox;
private _browseFileButton?: Button;
private _destinationRestoreToInputBox?: InputBox;
private _restoreFromSelectBox?: SelectBox;
private _sourceDatabaseSelectBox?: SelectBox;
private _panel: TabbedPanel;
private _generalTabId: PanelTabIdentifier;
private _panel?: TabbedPanel;
private _generalTabId?: PanelTabIdentifier;
// File option
private readonly _relocateDatabaseFilesOption = 'relocateDbFiles';
@@ -102,17 +102,17 @@ export class RestoreDialog extends Modal {
private readonly _closeExistingConnectionsOption = 'closeExistingConnections';
private _restoreFromBackupFileElement: HTMLElement;
private _restoreFromBackupFileElement?: HTMLElement;
private _fileListTable: Table<FileListElement>;
private _fileListData: TableDataView<FileListElement>;
private _fileListTableContainer: HTMLElement;
private _fileListTable?: Table<FileListElement>;
private _fileListData?: TableDataView<FileListElement>;
private _fileListTableContainer?: HTMLElement;
private _restorePlanTable: Table<Slick.SlickData>;
private _restorePlanData: TableDataView<Slick.SlickData>;
private _restorePlanColumn;
private _restorePlanTableContainer: HTMLElement;
private _isRenderedRestorePlanTable: boolean;
private _restorePlanTable?: Table<Slick.SlickData>;
private _restorePlanData?: TableDataView<Slick.SlickData>;
private _restorePlanColumn?: Slick.Column<Slick.SlickData>[];
private _restorePlanTableContainer?: HTMLElement;
private _isRenderedRestorePlanTable = false;
private _onRestore = new Emitter<boolean>();
public onRestore: Event<boolean> = this._onRestore.event;
@@ -142,10 +142,6 @@ export class RestoreDialog extends Modal {
@ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService
) {
super(localize('RestoreDialogTitle', "Restore database"), TelemetryKeys.Restore, telemetryService, layoutService, clipboardService, themeService, logService, textResourcePropertiesService, contextKeyService, { hasErrors: true, width: 'wide', 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);
@@ -157,8 +153,6 @@ export class RestoreDialog extends Modal {
this.viewModel.onSetRestoreOption((optionParams) => this.updateRestoreOption(optionParams));
this.viewModel.onUpdateBackupSetsToRestore((backupSets) => this.updateBackupSetsToRestore(backupSets));
this.viewModel.onUpdateRestoreDatabaseFiles((files) => this.updateRestoreDatabaseFiles(files));
this._isRenderedRestorePlanTable = false;
}
public render() {
@@ -169,7 +163,7 @@ export class RestoreDialog extends Modal {
this._restoreButton = this.addFooterButton(this._restoreLabel, () => this.restore(false));
this._closeButton = this.addFooterButton(cancelLabel, () => this.cancel());
this.registerListeners();
this._destinationRestoreToInputBox.disable();
this._destinationRestoreToInputBox!.disable();
}
protected renderBody(container: HTMLElement) {
@@ -228,14 +222,14 @@ export class RestoreDialog extends Modal {
});
this._databaseDropdown.onBlur(() => {
this.databaseSelected(this._databaseDropdown.value);
this.databaseSelected(this._databaseDropdown!.value);
});
this._databaseDropdown.onFocus(() => {
this._onDatabaseListFocused.fire();
});
this._databaseDropdown.value = this.viewModel.targetDatabaseName;
this._databaseDropdown.value = this.viewModel.targetDatabaseName!;
attachEditableDropdownStyler(this._databaseDropdown, this._themeService);
this._destinationRestoreToInputBox = this.createInputBoxHelper(destinationElement, localize('restoreTo', "Restore to"));
@@ -375,14 +369,14 @@ export class RestoreDialog extends Modal {
this._fileListTable.autosizeColumns();
}
if (c !== this._generalTabId) {
this._restoreFromSelectBox.hideMessage();
this._restoreFromSelectBox!.hideMessage();
}
});
this._restorePlanTable.grid.onKeyDown.subscribe(e => {
let event = new StandardKeyboardEvent(<unknown>e as KeyboardEvent);
if (event.equals(KeyMod.Shift | KeyCode.Tab)) {
this._destinationRestoreToInputBox.isEnabled() ? this._destinationRestoreToInputBox.focus() : this._databaseDropdown.focus();
this._destinationRestoreToInputBox!.isEnabled() ? this._destinationRestoreToInputBox!.focus() : this._databaseDropdown!.focus();
e.stopImmediatePropagation();
} else if (event.equals(KeyCode.Tab)) {
this.focusOnFirstEnabledFooterButton();
@@ -409,12 +403,12 @@ export class RestoreDialog extends Modal {
}
private focusOnFirstEnabledFooterButton() {
if (this._scriptButton.enabled) {
this._scriptButton.focus();
} else if (this._restoreButton.enabled) {
this._restoreButton.focus();
if (this._scriptButton!.enabled) {
this._scriptButton!.focus();
} else if (this._restoreButton!.enabled) {
this._restoreButton!.focus();
} else {
this._closeButton.focus();
this._closeButton!.focus();
}
}
@@ -426,7 +420,7 @@ export class RestoreDialog extends Modal {
}
public set databaseListOptions(vals: string[]) {
this._databaseDropdown.values = vals;
this._databaseDropdown!.values = vals;
}
private createLabelElement(container: HTMLElement, content: string, isHeader?: boolean) {
@@ -438,7 +432,7 @@ export class RestoreDialog extends Modal {
}
private createOptionControl(container: HTMLElement, optionName: string): void {
const option = this.viewModel.getOptionMetadata(optionName);
const option = this.viewModel.getOptionMetadata(optionName)!;
let propertyWidget: SelectBox | InputBox | Checkbox;
switch (option.valueType) {
case ServiceOptionType.boolean:
@@ -446,7 +440,7 @@ export class RestoreDialog extends Modal {
DialogHelper.getBooleanValueFromStringOrBoolean(option.defaultValue), () => this.onBooleanOptionChecked(optionName));
break;
case ServiceOptionType.category:
propertyWidget = this.createSelectBoxHelper(container, option.description, option.categoryValues.map(c => c.displayName), DialogHelper.getCategoryDisplayName(option.categoryValues, option.defaultValue));
propertyWidget = this.createSelectBoxHelper(container, option.description, option.categoryValues.map(c => c.displayName), DialogHelper.getCategoryDisplayName(option.categoryValues, option.defaultValue)!);
this._register(attachSelectBoxStyler(propertyWidget, this._themeService));
this._register(propertyWidget.onDidSelect(selectedDatabase => {
this.onCatagoryOptionChanged(optionName);
@@ -460,7 +454,7 @@ export class RestoreDialog extends Modal {
}));
}
this._optionsMap[optionName] = propertyWidget;
this._optionsMap[optionName] = propertyWidget!;
}
private onBooleanOptionChecked(optionName: string) {
@@ -510,46 +504,46 @@ export class RestoreDialog extends Modal {
}
private clearRestorePlanDataTable(): void {
if (this._restorePlanData.getLength() > 0) {
this._restorePlanData.clear();
DOM.hide(this._restorePlanTableContainer);
if (this._restorePlanData!.getLength() > 0) {
this._restorePlanData!.clear();
DOM.hide(this._restorePlanTableContainer!);
}
}
private clearFileListTable(): void {
if (this._fileListData.getLength() > 0) {
this._fileListData.clear();
DOM.hide(this._fileListTableContainer);
if (this._fileListData!.getLength() > 0) {
this._fileListData!.clear();
DOM.hide(this._fileListTableContainer!);
}
}
private resetRestoreContent(): void {
this.clearRestorePlanDataTable();
this.clearFileListTable();
this._restoreButton.enabled = false;
this._scriptButton.enabled = false;
this._restoreButton!.enabled = false;
this._scriptButton!.enabled = false;
}
public onValidateResponseFail(errorMessage: string) {
this.resetRestoreContent();
if (this.isRestoreFromDatabaseSelected) {
this._sourceDatabaseSelectBox.showMessage({ type: MessageType.ERROR, content: errorMessage });
this._sourceDatabaseSelectBox!.showMessage({ type: MessageType.ERROR, content: errorMessage });
} else {
this._sourceDatabaseSelectBox.setOptions([]);
this._filePathInputBox.showMessage({ type: MessageType.ERROR, content: errorMessage });
this._sourceDatabaseSelectBox!.setOptions([]);
this._filePathInputBox!.showMessage({ type: MessageType.ERROR, content: errorMessage });
}
}
public removeErrorMessage() {
this._filePathInputBox.hideMessage();
this._sourceDatabaseSelectBox.hideMessage();
this._destinationRestoreToInputBox.hideMessage();
this._filePathInputBox!.hideMessage();
this._sourceDatabaseSelectBox!.hideMessage();
this._destinationRestoreToInputBox!.hideMessage();
}
public enableRestoreButton(enabled: boolean) {
this.spinner = false;
this._restoreButton.enabled = enabled;
this._scriptButton.enabled = enabled;
this._restoreButton!.enabled = enabled;
this._scriptButton!.enabled = enabled;
}
public showError(errorMessage: string): void {
@@ -557,7 +551,7 @@ export class RestoreDialog extends Modal {
}
private backupFileCheckboxChanged(e: Slick.EventData, data: Slick.OnSelectedRowsChangedEventArgs<Slick.SlickData>): void {
let selectedFiles = [];
let selectedFiles: string[] = [];
data.grid.getSelectedRows().forEach(row => {
selectedFiles.push(data.grid.getDataItem(row)['Id']);
});
@@ -575,37 +569,37 @@ export class RestoreDialog extends Modal {
private registerListeners(): void {
// Theme styler
this._register(attachInputBoxStyler(this._filePathInputBox, this._themeService));
this._register(attachInputBoxStyler(this._destinationRestoreToInputBox, this._themeService));
this._register(attachSelectBoxStyler(this._restoreFromSelectBox, this._themeService));
this._register(attachSelectBoxStyler(this._sourceDatabaseSelectBox, this._themeService));
this._register(attachButtonStyler(this._browseFileButton, this._themeService));
this._register(attachButtonStyler(this._scriptButton, this._themeService));
this._register(attachButtonStyler(this._restoreButton, this._themeService));
this._register(attachButtonStyler(this._closeButton, this._themeService));
this._register(attachTableStyler(this._fileListTable, this._themeService));
this._register(attachTableStyler(this._restorePlanTable, this._themeService));
this._register(attachInputBoxStyler(this._filePathInputBox!, this._themeService));
this._register(attachInputBoxStyler(this._destinationRestoreToInputBox!, this._themeService));
this._register(attachSelectBoxStyler(this._restoreFromSelectBox!, this._themeService));
this._register(attachSelectBoxStyler(this._sourceDatabaseSelectBox!, this._themeService));
this._register(attachButtonStyler(this._browseFileButton!, this._themeService));
this._register(attachButtonStyler(this._scriptButton!, this._themeService));
this._register(attachButtonStyler(this._restoreButton!, this._themeService));
this._register(attachButtonStyler(this._closeButton!, this._themeService));
this._register(attachTableStyler(this._fileListTable!, this._themeService));
this._register(attachTableStyler(this._restorePlanTable!, this._themeService));
this._register(this._filePathInputBox.onLoseFocus(params => {
this._register(this._filePathInputBox!.onLoseFocus(params => {
this.onFilePathLoseFocus(params);
}));
this._browseFileButton.onDidClick(() => {
this._browseFileButton!.onDidClick(() => {
this.onFileBrowserRequested();
});
this._register(this._sourceDatabaseSelectBox.onDidSelect(selectedDatabase => {
this._register(this._sourceDatabaseSelectBox!.onDidSelect(selectedDatabase => {
this.onSourceDatabaseChanged(selectedDatabase.selected);
}));
this._register(this._restoreFromSelectBox.onDidSelect(selectedRestoreFrom => {
this._register(this._restoreFromSelectBox!.onDidSelect(selectedRestoreFrom => {
this.onRestoreFromChanged(selectedRestoreFrom.selected);
}));
}
private onFileBrowserRequested(): void {
this.fileBrowserDialogService.showDialog(this._ownerUri,
this.viewModel.defaultBackupFolder,
this.fileBrowserDialogService.showDialog(this._ownerUri!,
this.viewModel.defaultBackupFolder!,
fileFiltersSet,
FileValidationConstants.restore,
true,
@@ -613,15 +607,15 @@ export class RestoreDialog extends Modal {
}
private onFileBrowsed(filepath: string) {
const oldFilePath = this._filePathInputBox.value;
if (strings.isFalsyOrWhitespace(this._filePathInputBox.value)) {
this._filePathInputBox.value = filepath;
const oldFilePath = this._filePathInputBox!.value;
if (strings.isFalsyOrWhitespace(this._filePathInputBox!.value)) {
this._filePathInputBox!.value = filepath;
} else {
this._filePathInputBox.value = this._filePathInputBox.value + ', ' + filepath;
this._filePathInputBox!.value = this._filePathInputBox!.value + ', ' + filepath;
}
if (oldFilePath !== this._filePathInputBox.value) {
this.onFilePathChanged(this._filePathInputBox.value);
if (oldFilePath !== this._filePathInputBox!.value) {
this.onFilePathChanged(this._filePathInputBox!.value);
}
}
@@ -635,13 +629,13 @@ export class RestoreDialog extends Modal {
private onFilePathChanged(filePath: string) {
this.viewModel.filePath = filePath;
this.viewModel.selectedBackupSets = null;
this.viewModel.selectedBackupSets = undefined;
this.validateRestore(true);
}
private onSourceDatabaseChanged(selectedDatabase: string) {
this.viewModel.sourceDatabaseName = selectedDatabase;
this.viewModel.selectedBackupSets = null;
this.viewModel.selectedBackupSets = undefined;
this.validateRestore(true);
}
@@ -649,28 +643,28 @@ export class RestoreDialog extends Modal {
this.removeErrorMessage();
if (selectedRestoreFrom === this._backupFileTitle) {
this.viewModel.onRestoreFromChanged(true);
DOM.show(this._restoreFromBackupFileElement);
DOM.show(this._restoreFromBackupFileElement!);
} else {
this.viewModel.onRestoreFromChanged(false);
DOM.hide(this._restoreFromBackupFileElement);
DOM.hide(this._restoreFromBackupFileElement!);
}
this.resetRestoreContent();
}
private get isRestoreFromDatabaseSelected(): boolean {
return this._restoreFromSelectBox.value === this._databaseTitle;
return this._restoreFromSelectBox!.value === this._databaseTitle;
}
public validateRestore(overwriteTargetDatabase: boolean = false, isBackupFileCheckboxChanged: boolean = false): void {
this._isBackupFileCheckboxChanged = isBackupFileCheckboxChanged;
this.spinner = true;
this._restoreButton.enabled = false;
this._scriptButton.enabled = false;
this._restoreButton!.enabled = false;
this._scriptButton!.enabled = false;
this._onValidate.fire(overwriteTargetDatabase);
}
public restore(isScriptOnly: boolean): void {
if (this._restoreButton.enabled) {
if (this._restoreButton!.enabled) {
this._onRestore.fire(isScriptOnly);
}
}
@@ -702,10 +696,10 @@ export class RestoreDialog extends Modal {
private resetDialog(): void {
this.hideError();
this._restoreFromSelectBox.selectWithOptionName(this._databaseTitle);
this._restoreFromSelectBox!.selectWithOptionName(this._databaseTitle);
this.onRestoreFromChanged(this._databaseTitle);
this._sourceDatabaseSelectBox.select(0);
this._panel.showTab(this._generalTabId);
this._sourceDatabaseSelectBox!.select(0);
this._panel!.showTab(this._generalTabId!);
this._isBackupFileCheckboxChanged = false;
this.removeErrorMessage();
this.resetRestoreContent();
@@ -716,7 +710,7 @@ export class RestoreDialog extends Modal {
this._ownerUri = ownerUri;
this.show();
this._restoreFromSelectBox.focus();
this._restoreFromSelectBox!.focus();
}
protected layout(height?: number): void {
@@ -733,13 +727,13 @@ export class RestoreDialog extends Modal {
}
private updateLastBackupTaken(value: string) {
this._destinationRestoreToInputBox.value = value;
this._destinationRestoreToInputBox!.value = value;
}
private updateFilePath(value: string) {
this._filePathInputBox.value = value;
this._filePathInputBox!.value = value;
if (!value) {
this._filePathInputBox.hideMessage();
this._filePathInputBox!.hideMessage();
}
}
@@ -753,12 +747,12 @@ export class RestoreDialog extends Modal {
} else {
dbNames = databaseNamesParam.databaseNames;
}
this._sourceDatabaseSelectBox.setOptions(dbNames);
this._sourceDatabaseSelectBox.selectWithOptionName(databaseNamesParam.selectedDatabase);
this._sourceDatabaseSelectBox!.setOptions(dbNames);
this._sourceDatabaseSelectBox!.selectWithOptionName(databaseNamesParam.selectedDatabase);
}
private updateTargetDatabaseName(value: string) {
this._databaseDropdown.value = value;
this._databaseDropdown!.value = value;
}
private updateRestoreOption(optionParam: RestoreOptionParam) {
@@ -797,13 +791,13 @@ export class RestoreDialog extends Modal {
restoreAs: dbFiles[i].restoreAsFileName
};
}
DOM.show(this._fileListTableContainer);
this._fileListData.push(data);
DOM.show(this._fileListTableContainer!);
this._fileListData!.push(data);
// Set data and Select the first row for the table by default
this._fileListTable.setData(this._fileListData);
this._fileListTable.setSelectedRows([0]);
this._fileListTable.setActiveCell(0, 0);
this._fileListTable!.setData(this._fileListData!);
this._fileListTable!.setSelectedRows([0]);
this._fileListTable!.setActiveCell(0, 0);
}
}
@@ -815,7 +809,7 @@ export class RestoreDialog extends Modal {
selectedRow.push(i);
}
}
this._restorePlanTable.setSelectedRows(selectedRow);
this._restorePlanTable!.setSelectedRows(selectedRow);
} else {
this.clearRestorePlanDataTable();
if (backupSetsToRestore && backupSetsToRestore.length > 0) {
@@ -831,16 +825,16 @@ export class RestoreDialog extends Modal {
const checkboxSelectColumn = new CheckboxSelectColumn({ title: this._restoreLabel, toolTip: this._restoreLabel, width: 15 });
this._restorePlanColumn.unshift(checkboxSelectColumn.definition);
this._restorePlanTable.columns = this._restorePlanColumn;
this._restorePlanTable.registerPlugin(checkboxSelectColumn);
this._restorePlanTable.autosizeColumns();
this._restorePlanTable!.columns = this._restorePlanColumn;
this._restorePlanTable!.registerPlugin(checkboxSelectColumn);
this._restorePlanTable!.autosizeColumns();
}
const data = [];
const selectedRow = [];
const data: Slick.SlickData[] = [];
const selectedRow: number[] = [];
for (let i = 0; i < backupSetsToRestore.length; i++) {
const backupFile = backupSetsToRestore[i];
const newData = {};
const newData: Slick.SlickData = {};
for (let j = 0; j < backupFile.properties.length; j++) {
newData[backupFile.properties[j].propertyName] = backupFile.properties[j].propertyValueDisplayName;
}
@@ -849,15 +843,15 @@ export class RestoreDialog extends Modal {
selectedRow.push(i);
}
}
DOM.show(this._restorePlanTableContainer);
this._restorePlanData.push(data);
this._restorePlanTable.setSelectedRows(selectedRow);
this._restorePlanTable.setActiveCell(selectedRow[0], 0);
DOM.show(this._restorePlanTableContainer!);
this._restorePlanData!.push(data);
this._restorePlanTable!.setSelectedRows(selectedRow);
this._restorePlanTable!.setActiveCell(selectedRow[0], 0);
if (!this._isRenderedRestorePlanTable) {
this._isRenderedRestorePlanTable = true;
this._restorePlanTable.resizeCanvas();
this._restorePlanTable.autosizeColumns();
this._restorePlanTable!.resizeCanvas();
this._restorePlanTable!.autosizeColumns();
}
}
}

View File

@@ -22,7 +22,6 @@ import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { invalidProvider } from 'sql/base/common/errors';
import { ILogService } from 'vs/platform/log/common/log';
import { find } from 'vs/base/common/arrays';
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
export class RestoreService implements IRestoreService {
@@ -76,7 +75,7 @@ export class RestoreService implements IRestoreService {
});
}
private getProvider(connectionUri: string): { provider: azdata.RestoreProvider, providerName: string } {
private getProvider(connectionUri: string): { provider: azdata.RestoreProvider, providerName: string } | undefined {
let providerId: string = this._connectionService.getProviderIdFromUri(connectionUri);
if (providerId) {
return { provider: this._providers[providerId], providerName: providerId };
@@ -135,9 +134,9 @@ export class RestoreDialogController implements IRestoreDialogController {
_serviceBrand: undefined;
private _restoreDialogs: { [provider: string]: RestoreDialog | OptionsDialog } = {};
private _currentProvider: string;
private _ownerUri: string;
private _sessionId: string;
private _currentProvider?: string;
private _ownerUri?: string;
private _sessionId?: string;
private readonly _restoreFeature = 'Restore';
private readonly _restoreTaskName: string = 'Restore Database';
private readonly _restoreCompleted: string = 'Completed';
@@ -157,21 +156,20 @@ export class RestoreDialogController implements IRestoreDialogController {
private handleOnRestore(isScriptOnly: boolean = false): void {
let restoreOption = this.setRestoreOption(isScriptOnly ? TaskExecutionMode.script : TaskExecutionMode.executeAndScript);
this._restoreService.restore(this._ownerUri, restoreOption).then(result => {
const self = this;
let connectionProfile = self._connectionService.getConnectionProfile(self._ownerUri);
let activeNode = self._objectExplorerService.getObjectExplorerNode(connectionProfile);
this._restoreService.restore(this._ownerUri!, restoreOption).then(result => {
let connectionProfile = this._connectionService.getConnectionProfile(this._ownerUri!);
let activeNode = this._objectExplorerService.getObjectExplorerNode(connectionProfile)!;
this._taskService.onTaskComplete(async response => {
if (result.taskId === response.id && this.isSuccessfulRestore(response) && activeNode) {
try {
await self._objectExplorerService.refreshTreeNode(activeNode.getSession(), activeNode);
await self._objectExplorerService.getServerTreeView().refreshTree();
await this._objectExplorerService.refreshTreeNode(activeNode.getSession()!, activeNode);
await this._objectExplorerService.getServerTreeView()!.refreshTree();
} catch (e) {
this._logService.error(e);
}
}
});
let restoreDialog = this._restoreDialogs[this._currentProvider];
let restoreDialog = this._restoreDialogs[this._currentProvider!];
restoreDialog.close();
});
}
@@ -186,8 +184,8 @@ export class RestoreDialogController implements IRestoreDialogController {
}
private handleMssqlOnValidateFile(overwriteTargetDatabase: boolean = false): void {
let restoreDialog = this._restoreDialogs[this._currentProvider] as RestoreDialog;
this._restoreService.getRestorePlan(this._ownerUri, this.setRestoreOption(TaskExecutionMode.execute, overwriteTargetDatabase)).then(restorePlanResponse => {
let restoreDialog = this._restoreDialogs[this._currentProvider!] as RestoreDialog;
this._restoreService.getRestorePlan(this._ownerUri!, this.setRestoreOption(TaskExecutionMode.execute, overwriteTargetDatabase)).then(restorePlanResponse => {
this._sessionId = restorePlanResponse.sessionId;
if (restorePlanResponse.errorMessage) {
@@ -212,7 +210,7 @@ export class RestoreDialogController implements IRestoreDialogController {
* Will remove this function once there is a fix in the service (bug #2572)
*/
private isEmptyBackupset(): boolean {
let restoreDialog = this._restoreDialogs[this._currentProvider] as RestoreDialog;
let restoreDialog = this._restoreDialogs[this._currentProvider!] as RestoreDialog;
if (!types.isUndefinedOrNull(restoreDialog.viewModel.selectedBackupSets) && restoreDialog.viewModel.selectedBackupSets.length === 0) {
return true;
}
@@ -221,8 +219,8 @@ export class RestoreDialogController implements IRestoreDialogController {
private getMssqlRestoreConfigInfo(): Promise<void> {
return new Promise<void>((resolve, reject) => {
let restoreDialog = this._restoreDialogs[this._currentProvider] as RestoreDialog;
this._restoreService.getRestoreConfigInfo(this._ownerUri).then(restoreConfigInfo => {
let restoreDialog = this._restoreDialogs[this._currentProvider!] as RestoreDialog;
this._restoreService.getRestoreConfigInfo(this._ownerUri!).then(restoreConfigInfo => {
restoreDialog.viewModel.updateOptionWithConfigInfo(restoreConfigInfo.configInfo);
resolve();
}, error => {
@@ -233,22 +231,20 @@ export class RestoreDialogController implements IRestoreDialogController {
}
private setRestoreOption(taskExecutionMode: TaskExecutionMode, overwriteTargetDatabase: boolean = false): azdata.RestoreInfo {
let restoreInfo = undefined;
let providerId: string = this.getCurrentProviderId();
if (providerId === ConnectionConstants.mssqlProviderName) {
restoreInfo = new MssqlRestoreInfo(taskExecutionMode);
let restoreInfo = new MssqlRestoreInfo(taskExecutionMode);
if (this._sessionId) {
restoreInfo.sessionId = this._sessionId;
}
let restoreDialog = this._restoreDialogs[providerId] as RestoreDialog;
restoreInfo.backupFilePaths = restoreDialog.viewModel.filePath;
restoreInfo.backupFilePaths = restoreDialog.viewModel.filePath!;
restoreInfo.readHeaderFromMedia = restoreDialog.viewModel.readHeaderFromMedia;
restoreInfo.selectedBackupSets = restoreDialog.viewModel.selectedBackupSets;
restoreInfo.sourceDatabaseName = restoreDialog.viewModel.sourceDatabaseName;
restoreInfo.readHeaderFromMedia = restoreDialog.viewModel.readHeaderFromMedia!;
restoreInfo.selectedBackupSets = restoreDialog.viewModel.selectedBackupSets!;
restoreInfo.sourceDatabaseName = restoreDialog.viewModel.sourceDatabaseName!;
if (restoreDialog.viewModel.targetDatabaseName) {
restoreInfo.targetDatabaseName = restoreDialog.viewModel.targetDatabaseName;
}
@@ -256,11 +252,10 @@ export class RestoreDialogController implements IRestoreDialogController {
// Set other restore options
restoreDialog.viewModel.getRestoreAdvancedOptions(restoreInfo.options);
return restoreInfo;
} else {
restoreInfo = { options: this._optionValues };
return { options: this._optionValues };
}
return restoreInfo;
}
private getRestoreOption(): azdata.ServiceOption[] {
@@ -269,7 +264,7 @@ export class RestoreDialogController implements IRestoreDialogController {
let providerCapabilities = this._capabilitiesService.getLegacyCapabilities(providerId);
if (providerCapabilities) {
let restoreMetadataProvider = find(providerCapabilities.features, f => f.featureName === this._restoreFeature);
let restoreMetadataProvider = providerCapabilities.features.find(f => f.featureName === this._restoreFeature);
if (restoreMetadataProvider) {
options = restoreMetadataProvider.optionsMetadata;
}
@@ -278,14 +273,14 @@ export class RestoreDialogController implements IRestoreDialogController {
}
private handleOnClose(): void {
this._connectionService.disconnect(this._ownerUri).catch((e) => this._logService.error(e));
this._connectionService.disconnect(this._ownerUri!).catch((e) => this._logService.error(e));
}
private handleOnCancel(): void {
let restoreInfo = new MssqlRestoreInfo(TaskExecutionMode.execute);
restoreInfo.sessionId = this._sessionId;
this._restoreService.cancelRestorePlan(this._ownerUri, restoreInfo).then(() => {
this._connectionService.disconnect(this._ownerUri);
restoreInfo.sessionId = this._sessionId!;
this._restoreService.cancelRestorePlan(this._ownerUri!, restoreInfo).then(() => {
this._connectionService.disconnect(this._ownerUri!);
});
}
@@ -301,10 +296,10 @@ export class RestoreDialogController implements IRestoreDialogController {
if (!this._connectionService.isConnected(this._ownerUri)) {
this._connectionService.connect(connection, this._ownerUri).then(connectionResult => {
this._sessionId = null;
this._sessionId = undefined;
this._currentProvider = this.getCurrentProviderId();
if (!this._restoreDialogs[this._currentProvider]) {
let newRestoreDialog: RestoreDialog | OptionsDialog = undefined;
let newRestoreDialog: RestoreDialog | OptionsDialog;
if (this._currentProvider === ConnectionConstants.mssqlProviderName) {
let provider = this._currentProvider;
newRestoreDialog = this._instantiationService.createInstance(RestoreDialog, this.getRestoreOption());
@@ -326,7 +321,7 @@ export class RestoreDialogController implements IRestoreDialogController {
let restoreDialog = this._restoreDialogs[this._currentProvider] as RestoreDialog;
restoreDialog.viewModel.resetRestoreOptions(connection.databaseName);
this.getMssqlRestoreConfigInfo().then(() => {
restoreDialog.open(connection.serverName, this._ownerUri);
restoreDialog.open(connection.serverName, this._ownerUri!);
restoreDialog.validateRestore();
}, restoreConfigError => {
reject(restoreConfigError);
@@ -345,11 +340,11 @@ export class RestoreDialogController implements IRestoreDialogController {
}
private getCurrentProviderId(): string {
return this._connectionService.getProviderIdFromUri(this._ownerUri);
return this._connectionService.getProviderIdFromUri(this._ownerUri!);
}
private fetchDatabases(provider: string): void {
this._connectionService.listDatabases(this._ownerUri).then(result => {
this._connectionService.listDatabases(this._ownerUri!).then(result => {
if (result && result.databaseNames) {
(<RestoreDialog>this._restoreDialogs[provider]).databaseListOptions = result.databaseNames;
}

View File

@@ -9,6 +9,7 @@ import * as types from 'vs/base/common/types';
import { Event, Emitter } from 'vs/base/common/event';
import { ServiceOptionType } from 'sql/workbench/api/common/sqlExtHostTypes';
import { coalesce } from 'vs/base/common/arrays';
export interface RestoreOptionsElement {
optionMetadata: azdata.ServiceOption;
@@ -30,21 +31,21 @@ export interface RestoreOptionParam {
*/
export interface SouceDatabaseNamesParam {
databaseNames: string[];
selectedDatabase: string;
selectedDatabase?: string;
}
/**
* View model for restore dialog
*/
export class RestoreViewModel {
public filePath: string;
public sourceDatabaseName: string;
public targetDatabaseName: string;
public lastBackupTaken: string;
public databaseList: string[];
public readHeaderFromMedia: boolean;
public selectedBackupSets: string[];
public defaultBackupFolder: string;
public filePath?: string;
public sourceDatabaseName?: string;
public targetDatabaseName?: string;
public lastBackupTaken?: string;
public databaseList?: string[];
public readHeaderFromMedia?: boolean;
public selectedBackupSets?: string[];
public defaultBackupFolder?: string;
private _onSetLastBackupTaken = new Emitter<string>();
public onSetLastBackupTaken: Event<string> = this._onSetLastBackupTaken.event;
@@ -111,14 +112,14 @@ export class RestoreViewModel {
this.updateFilePath('');
this.updateSourceDatabaseNames([], undefined);
} else {
this.updateSourceDatabaseNames(this.databaseList, this.databaseList[0]);
this.updateSourceDatabaseNames(this.databaseList!, this.databaseList![0]);
}
}
/**
* Get option metadata from the option map
*/
public getOptionMetadata(optionName: string): azdata.ServiceOption {
public getOptionMetadata(optionName: string): azdata.ServiceOption | undefined {
return this._optionsMap[optionName] ? this._optionsMap[optionName].optionMetadata : undefined;
}
@@ -234,14 +235,9 @@ export class RestoreViewModel {
* Update backup sets to restore
*/
public updateBackupSetsToRestore(backupSetsToRestore: azdata.DatabaseFileInfo[]): void {
this.selectedBackupSets = null;
this.selectedBackupSets = undefined;
if (backupSetsToRestore) {
this.selectedBackupSets = [];
backupSetsToRestore.forEach(backupFile => {
if (backupFile.isSelected) {
this.selectedBackupSets.push(backupFile.id);
}
});
this.selectedBackupSets = coalesce(backupSetsToRestore.map(f => f.isSelected ? f.id : undefined));
this._onUpdateBackupSetsToRestore.fire(backupSetsToRestore);
}
}
@@ -256,7 +252,7 @@ export class RestoreViewModel {
this.updateFilePath('');
this.updateLastBackupTaken('');
this.databaseList = [];
this.selectedBackupSets = null;
this.selectedBackupSets = undefined;
for (let key in this._optionsMap) {
this._optionsMap[key].defaultValue = this.getDisplayValue(this._optionsMap[key].optionMetadata, this._optionsMap[key].optionMetadata.defaultValue);
this._optionsMap[key].currentValue = this._optionsMap[key].defaultValue;
@@ -283,7 +279,7 @@ export class RestoreViewModel {
/**
* Update source database names and selected database
*/
public updateSourceDatabaseNames(options: string[], selectedDatabase: string) {
public updateSourceDatabaseNames(options: string[], selectedDatabase?: string) {
this.sourceDatabaseName = selectedDatabase;
this._onSetSourceDatabaseNames.fire({ databaseNames: options, selectedDatabase: selectedDatabase });
}

View File

@@ -73,12 +73,12 @@ suite('Restore Dialog view model tests', () => {
stringServiceOption = {
name: option1String,
displayName: 'Option 1',
description: null,
groupName: null,
description: null!,
groupName: null!,
valueType: ServiceOptionType.string,
defaultValue: 'default',
objectType: null,
categoryValues: null,
objectType: null!,
categoryValues: null!,
isRequired: false,
isArray: false
};
@@ -86,11 +86,11 @@ suite('Restore Dialog view model tests', () => {
categoryServiceOption = {
name: option2Category,
displayName: 'Option 2',
description: null,
groupName: null,
description: null!,
groupName: null!,
valueType: ServiceOptionType.category,
defaultValue: 'catagory1',
objectType: null,
objectType: null!,
categoryValues: [{
displayName: 'Catagory 1',
name: 'catagory1'
@@ -106,12 +106,12 @@ suite('Restore Dialog view model tests', () => {
booleanServiceOption = {
name: option3Boolean,
displayName: 'Option 3',
description: null,
groupName: null,
description: null!,
groupName: null!,
valueType: ServiceOptionType.boolean,
defaultValue: 'true',
objectType: null,
categoryValues: null,
objectType: null!,
categoryValues: null!,
isRequired: false,
isArray: false
};
@@ -171,7 +171,6 @@ suite('Restore Dialog view model tests', () => {
sessionId: '123',
backupSetsToRestore: backupSets,
canRestore: true,
errorMessage: null,
dbFiles: [],
databaseNamesFromBackupSets: ['dbSource', 'dbSource2'],
planDetails: planDetails
@@ -191,8 +190,8 @@ suite('Restore Dialog view model tests', () => {
// verify that selected backup sets get set correctly
let selectedBackupSets = viewModel.selectedBackupSets;
assert.equal(1, selectedBackupSets.length);
assert.equal('file2', selectedBackupSets[0]);
assert.equal(1, selectedBackupSets!.length);
assert.equal('file2', selectedBackupSets![0]);
});
@@ -201,7 +200,6 @@ suite('Restore Dialog view model tests', () => {
sessionId: '123',
backupSetsToRestore: backupSets,
canRestore: true,
errorMessage: null,
dbFiles: [],
databaseNamesFromBackupSets: ['dbSource', 'dbSource2'],
planDetails: planDetails
@@ -217,7 +215,7 @@ suite('Restore Dialog view model tests', () => {
assert.equal('db2', viewModel.sourceDatabaseName);
assert.equal('db2', viewModel.targetDatabaseName);
assert.equal('', viewModel.lastBackupTaken);
assert.equal(0, viewModel.databaseList.length);
assert.equal(0, viewModel.databaseList!.length);
// verify that advanced options get set correctly
options = {};
@@ -235,10 +233,11 @@ suite('Restore Dialog view model tests', () => {
configInfo['sourceDatabaseNamesWithBackupSets'] = databaseList;
configInfo[option1String] = 'option1 from config info';
viewModel.updateOptionWithConfigInfo(configInfo);
assert.equal(3, viewModel.databaseList.length);
assert.equal('', viewModel.databaseList[0]);
assert.equal(databaseList[1], viewModel.databaseList[1]);
assert.equal(databaseList[2], viewModel.databaseList[2]);
assert.ok(viewModel.databaseList);
assert.equal(3, viewModel.databaseList!.length);
assert.equal('', viewModel.databaseList![0]);
assert.equal(databaseList[1], viewModel.databaseList![1]);
assert.equal(databaseList[2], viewModel.databaseList![2]);
assert.equal('option1 from config info', viewModel.getOptionValue(option1String));
// verify that the options from get restore advanced options doesn't contain option1String