strict compile contrib/backup (#12088)

This commit is contained in:
Anthony Dresser
2020-09-03 11:50:53 -07:00
committed by GitHub
parent 528fbb14ea
commit b7c2eaa65d
8 changed files with 284 additions and 287 deletions

5
src/sql/azdata.d.ts vendored
View File

@@ -1879,7 +1879,10 @@ declare module 'azdata' {
export interface BackupConfigInfo { export interface BackupConfigInfo {
recoveryModel: string; recoveryModel: string;
defaultBackupFolder: string; defaultBackupFolder: string;
backupEncryptors: {}; backupEncryptors: {
encryptorType: number;
encryptorName: string;
}[];
} }
export interface BackupResponse { export interface BackupResponse {

View File

@@ -57,11 +57,11 @@ interface MssqlBackupInfo {
backupDeviceType: number; backupDeviceType: number;
selectedFiles: string; selectedFiles: string;
backupsetName: string; backupsetName: string;
selectedFileGroup: { [path: string]: string }; selectedFileGroup?: { [path: string]: string };
// List of {key: backup path, value: device type} // List of {key: backup path, value: device type}
backupPathDevices: { [path: string]: number }; backupPathDevices: { [path: string]: number };
backupPathList: [string]; backupPathList: string[];
isCopyOnly: boolean; isCopyOnly: boolean;
formatMedia: boolean; formatMedia: boolean;
initialize: boolean; initialize: boolean;
@@ -76,7 +76,7 @@ interface MssqlBackupInfo {
compressionOption: number; compressionOption: number;
verifyBackupRequired: boolean; verifyBackupRequired: boolean;
encryptionAlgorithm: number; encryptionAlgorithm: number;
encryptorType: number; encryptorType?: number;
encryptorName: string; encryptorName: string;
} }
@@ -117,83 +117,86 @@ const LocalizedStrings = {
templateUrl: decodeURI(require.toUrl('./backup.component.html')) templateUrl: decodeURI(require.toUrl('./backup.component.html'))
}) })
export class BackupComponent extends AngularDisposable { export class BackupComponent extends AngularDisposable {
@ViewChild('pathContainer', { read: ElementRef }) pathElement; @ViewChild('pathContainer', { read: ElementRef }) pathElement?: ElementRef;
@ViewChild('backupTypeContainer', { read: ElementRef }) backupTypeElement; @ViewChild('backupTypeContainer', { read: ElementRef }) backupTypeElement?: ElementRef;
@ViewChild('backupsetName', { read: ElementRef }) backupNameElement; @ViewChild('backupsetName', { read: ElementRef }) backupNameElement?: ElementRef;
@ViewChild('compressionContainer', { read: ElementRef }) compressionElement; @ViewChild('compressionContainer', { read: ElementRef }) compressionElement?: ElementRef;
@ViewChild('tlogOption', { read: ElementRef }) tlogOptionElement; @ViewChild('tlogOption', { read: ElementRef }) tlogOptionElement?: ElementRef;
@ViewChild('algorithmContainer', { read: ElementRef }) encryptionAlgorithmElement; @ViewChild('algorithmContainer', { read: ElementRef }) encryptionAlgorithmElement?: ElementRef;
@ViewChild('encryptorContainer', { read: ElementRef }) encryptorElement; @ViewChild('encryptorContainer', { read: ElementRef }) encryptorElement?: ElementRef;
@ViewChild('mediaName', { read: ElementRef }) mediaNameElement; @ViewChild('mediaName', { read: ElementRef }) mediaNameElement?: ElementRef;
@ViewChild('mediaDescription', { read: ElementRef }) mediaDescriptionElement; @ViewChild('mediaDescription', { read: ElementRef }) mediaDescriptionElement?: ElementRef;
@ViewChild('recoveryModelContainer', { read: ElementRef }) recoveryModelElement; @ViewChild('recoveryModelContainer', { read: ElementRef }) recoveryModelElement?: ElementRef;
@ViewChild('backupDaysContainer', { read: ElementRef }) backupDaysElement; @ViewChild('backupDaysContainer', { read: ElementRef }) backupDaysElement?: ElementRef;
@ViewChild('backupButtonContainer', { read: ElementRef }) backupButtonElement; @ViewChild('backupButtonContainer', { read: ElementRef }) backupButtonElement?: ElementRef;
@ViewChild('cancelButtonContainer', { read: ElementRef }) cancelButtonElement; @ViewChild('cancelButtonContainer', { read: ElementRef }) cancelButtonElement?: ElementRef;
@ViewChild('addPathContainer', { read: ElementRef }) addPathElement; @ViewChild('addPathContainer', { read: ElementRef }) addPathElement?: ElementRef;
@ViewChild('removePathContainer', { read: ElementRef }) removePathElement; @ViewChild('removePathContainer', { read: ElementRef }) removePathElement?: ElementRef;
@ViewChild('copyOnlyContainer', { read: ElementRef }) copyOnlyElement; @ViewChild('copyOnlyContainer', { read: ElementRef }) copyOnlyElement?: ElementRef;
@ViewChild('encryptCheckContainer', { read: ElementRef }) encryptElement; @ViewChild('encryptCheckContainer', { read: ElementRef }) encryptElement?: ElementRef;
@ViewChild('encryptContainer', { read: ElementRef }) encryptContainerElement; @ViewChild('encryptContainer', { read: ElementRef }) encryptContainerElement?: ElementRef;
@ViewChild('verifyContainer', { read: ElementRef }) verifyElement; @ViewChild('verifyContainer', { read: ElementRef }) verifyElement?: ElementRef;
@ViewChild('checksumContainer', { read: ElementRef }) checksumElement; @ViewChild('checksumContainer', { read: ElementRef }) checksumElement?: ElementRef;
@ViewChild('continueOnErrorContainer', { read: ElementRef }) continueOnErrorElement; @ViewChild('continueOnErrorContainer', { read: ElementRef }) continueOnErrorElement?: ElementRef;
@ViewChild('encryptWarningContainer', { read: ElementRef }) encryptWarningElement; @ViewChild('encryptWarningContainer', { read: ElementRef }) encryptWarningElement?: ElementRef;
@ViewChild('inProgressContainer', { read: ElementRef }) inProgressElement; @ViewChild('inProgressContainer', { read: ElementRef }) inProgressElement?: ElementRef;
@ViewChild('modalFooterContainer', { read: ElementRef }) modalFooterElement; @ViewChild('modalFooterContainer', { read: ElementRef }) modalFooterElement?: ElementRef;
@ViewChild('scriptButtonContainer', { read: ElementRef }) scriptButtonElement; @ViewChild('scriptButtonContainer', { read: ElementRef }) scriptButtonElement?: ElementRef;
@ViewChild('advancedOptionContainer', { read: ElementRef }) advancedOptionElement; @ViewChild('advancedOptionContainer', { read: ElementRef }) advancedOptionElement?: ElementRef;
@ViewChild('advancedOptionBodyContainer', { read: ElementRef }) advancedOptionBodyElement; @ViewChild('advancedOptionBodyContainer', { read: ElementRef }) advancedOptionBodyElement?: ElementRef;
private localizedStrings = LocalizedStrings; private localizedStrings = LocalizedStrings;
private _uri: string; private _uri?: string;
private connection: IConnectionProfile; private connection?: IConnectionProfile;
private databaseName: string; private databaseName?: string;
private defaultNewBackupFolder: string; private defaultNewBackupFolder?: string;
private recoveryModel: string; private recoveryModel?: string;
private backupEncryptors; private backupEncryptors?: {
private containsBackupToUrl: boolean; encryptorType: number;
encryptorName: string;
}[];
private containsBackupToUrl?: boolean;
// UI element disable flag // UI element disable flag
public disableTlog: boolean; public disableTlog?: boolean;
public selectedBackupComponent: string; public selectedBackupComponent?: string;
private selectedFilesText: string; private selectedFilesText?: string;
private selectedInitOption: string; private selectedInitOption?: string;
private isTruncateChecked: boolean; private isTruncateChecked?: boolean;
private isTaillogChecked: boolean; private isTaillogChecked?: boolean;
private isFormatChecked: boolean; private isFormatChecked?: boolean;
public isEncryptChecked: boolean; public isEncryptChecked?: boolean;
// Key: backup path, Value: device type // Key: backup path, Value: device type
private backupPathTypePairs: { [path: string]: number }; private backupPathTypePairs?: { [path: string]: number };
private compressionOptions = [BackupConstants.defaultCompression, BackupConstants.compressionOn, BackupConstants.compressionOff]; private compressionOptions = [BackupConstants.defaultCompression, BackupConstants.compressionOn, BackupConstants.compressionOff];
private encryptionAlgorithms = [BackupConstants.aes128, BackupConstants.aes192, BackupConstants.aes256, BackupConstants.tripleDES]; private encryptionAlgorithms = [BackupConstants.aes128, BackupConstants.aes192, BackupConstants.aes256, BackupConstants.tripleDES];
private existingMediaOptions = ['append', 'overwrite']; private existingMediaOptions = ['append', 'overwrite'];
private backupTypeOptions: string[]; private backupTypeOptions?: string[];
private backupTypeSelectBox: SelectBox; private backupTypeSelectBox?: SelectBox;
private backupNameBox: InputBox; private backupNameBox?: InputBox;
private recoveryBox: InputBox; private recoveryBox?: InputBox;
private backupRetainDaysBox: InputBox; private backupRetainDaysBox?: InputBox;
private backupButton: Button; private backupButton?: Button;
private cancelButton: Button; private cancelButton?: Button;
private scriptButton: Button; private scriptButton?: Button;
private addPathButton: Button; private addPathButton?: Button;
private removePathButton: Button; private removePathButton?: Button;
private pathListBox: ListBox; private pathListBox?: ListBox;
private compressionSelectBox: SelectBox; private compressionSelectBox?: SelectBox;
private algorithmSelectBox: SelectBox; private algorithmSelectBox?: SelectBox;
private encryptorSelectBox: SelectBox; private encryptorSelectBox?: SelectBox;
private mediaNameBox: InputBox; private mediaNameBox?: InputBox;
private mediaDescriptionBox: InputBox; private mediaDescriptionBox?: InputBox;
private copyOnlyCheckBox: Checkbox; private copyOnlyCheckBox?: Checkbox;
private encryptCheckBox: Checkbox; private encryptCheckBox?: Checkbox;
private verifyCheckBox: Checkbox; private verifyCheckBox?: Checkbox;
private checksumCheckBox: Checkbox; private checksumCheckBox?: Checkbox;
private continueOnErrorCheckBox: Checkbox; private continueOnErrorCheckBox?: Checkbox;
constructor( constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeDetectorRef: ChangeDetectorRef, @Inject(forwardRef(() => ChangeDetectorRef)) private _changeDetectorRef: ChangeDetectorRef,
@@ -210,19 +213,18 @@ export class BackupComponent extends AngularDisposable {
} }
ngOnInit() { ngOnInit() {
let self = this;
this.addFooterButtons(); this.addFooterButtons();
this.recoveryBox = new InputBox(this.recoveryModelElement.nativeElement, this.contextViewService, { this.recoveryBox = new InputBox(this.recoveryModelElement!.nativeElement, this.contextViewService, {
placeholder: this.recoveryModel, placeholder: this.recoveryModel,
ariaLabel: LocalizedStrings.RECOVERY_MODEL ariaLabel: LocalizedStrings.RECOVERY_MODEL
}); });
// Set backup type // Set backup type
this.backupTypeSelectBox = new SelectBox([], '', this.contextViewService, undefined, { ariaLabel: this.localizedStrings.BACKUP_TYPE }); this.backupTypeSelectBox = new SelectBox([], '', this.contextViewService, undefined, { ariaLabel: this.localizedStrings.BACKUP_TYPE });
this.backupTypeSelectBox.render(this.backupTypeElement.nativeElement); this.backupTypeSelectBox.render(this.backupTypeElement!.nativeElement);
// Set copy-only check box // Set copy-only check box
this.copyOnlyCheckBox = new Checkbox(this.copyOnlyElement.nativeElement, { this.copyOnlyCheckBox = new Checkbox(this.copyOnlyElement!.nativeElement, {
label: LocalizedStrings.COPY_ONLY, label: LocalizedStrings.COPY_ONLY,
checked: false, checked: false,
onChange: (viaKeyboard) => { }, onChange: (viaKeyboard) => { },
@@ -230,39 +232,39 @@ export class BackupComponent extends AngularDisposable {
}); });
// Encryption checkbox // Encryption checkbox
this.encryptCheckBox = new Checkbox(this.encryptElement.nativeElement, { this.encryptCheckBox = new Checkbox(this.encryptElement!.nativeElement, {
label: LocalizedStrings.ENCRYPTION, label: LocalizedStrings.ENCRYPTION,
checked: false, checked: false,
onChange: (viaKeyboard) => self.onChangeEncrypt(), onChange: () => this.onChangeEncrypt(),
ariaLabel: LocalizedStrings.ENCRYPTION ariaLabel: LocalizedStrings.ENCRYPTION
}); });
// Verify backup checkbox // Verify backup checkbox
this.verifyCheckBox = new Checkbox(this.verifyElement.nativeElement, { this.verifyCheckBox = new Checkbox(this.verifyElement!.nativeElement, {
label: LocalizedStrings.VERIFY_CONTAINER, label: LocalizedStrings.VERIFY_CONTAINER,
checked: false, checked: false,
onChange: (viaKeyboard) => { }, onChange: () => { },
ariaLabel: LocalizedStrings.VERIFY_CONTAINER ariaLabel: LocalizedStrings.VERIFY_CONTAINER
}); });
// Perform checksum checkbox // Perform checksum checkbox
this.checksumCheckBox = new Checkbox(this.checksumElement.nativeElement, { this.checksumCheckBox = new Checkbox(this.checksumElement!.nativeElement, {
label: LocalizedStrings.CHECKSUM_CONTAINER, label: LocalizedStrings.CHECKSUM_CONTAINER,
checked: false, checked: false,
onChange: (viaKeyboard) => { }, onChange: () => { },
ariaLabel: LocalizedStrings.CHECKSUM_CONTAINER ariaLabel: LocalizedStrings.CHECKSUM_CONTAINER
}); });
// Continue on error checkbox // Continue on error checkbox
this.continueOnErrorCheckBox = new Checkbox(this.continueOnErrorElement.nativeElement, { this.continueOnErrorCheckBox = new Checkbox(this.continueOnErrorElement!.nativeElement, {
label: LocalizedStrings.CONTINUE_ON_ERROR_CONTAINER, label: LocalizedStrings.CONTINUE_ON_ERROR_CONTAINER,
checked: false, checked: false,
onChange: (viaKeyboard) => { }, onChange: () => { },
ariaLabel: LocalizedStrings.CONTINUE_ON_ERROR_CONTAINER ariaLabel: LocalizedStrings.CONTINUE_ON_ERROR_CONTAINER
}); });
// Set backup name // Set backup name
this.backupNameBox = new InputBox(this.backupNameElement.nativeElement, this.contextViewService, { this.backupNameBox = new InputBox(this.backupNameElement!.nativeElement, this.contextViewService, {
ariaLabel: LocalizedStrings.BACKUP_NAME ariaLabel: LocalizedStrings.BACKUP_NAME
}); });
@@ -270,14 +272,14 @@ export class BackupComponent extends AngularDisposable {
this.pathListBox = new ListBox([], this.contextViewService); this.pathListBox = new ListBox([], this.contextViewService);
this.pathListBox.setAriaLabel(LocalizedStrings.BACKUP_DEVICE); this.pathListBox.setAriaLabel(LocalizedStrings.BACKUP_DEVICE);
this.pathListBox.onKeyDown(e => { this.pathListBox.onKeyDown(e => {
if (this.pathListBox.selectedOptions.length > 0) { if (this.pathListBox!.selectedOptions.length > 0) {
const key = e.keyCode; const key = e.keyCode;
const ctrlOrCmd = e.ctrlKey || e.metaKey; const ctrlOrCmd = e.ctrlKey || e.metaKey;
if (ctrlOrCmd && key === KeyCode.KEY_C) { if (ctrlOrCmd && key === KeyCode.KEY_C) {
let textToCopy = this.pathListBox.selectedOptions[0]; let textToCopy = this.pathListBox!.selectedOptions[0];
for (let i = 1; i < this.pathListBox.selectedOptions.length; i++) { for (let i = 1; i < this.pathListBox!.selectedOptions.length; i++) {
textToCopy = textToCopy + ', ' + this.pathListBox.selectedOptions[i]; textToCopy = textToCopy + ', ' + this.pathListBox!.selectedOptions[i];
} }
// Copy to clipboard // Copy to clipboard
@@ -287,29 +289,29 @@ export class BackupComponent extends AngularDisposable {
} }
} }
}); });
this.pathListBox.render(this.pathElement.nativeElement); this.pathListBox.render(this.pathElement!.nativeElement);
// Set backup path add/remove buttons // Set backup path add/remove buttons
this.addPathButton = this._register(new Button(this.addPathElement.nativeElement)); this.addPathButton = this._register(new Button(this.addPathElement!.nativeElement));
this.addPathButton.label = '+'; this.addPathButton.label = '+';
this.addPathButton.title = localize('addFile', "Add a file"); this.addPathButton.title = localize('addFile', "Add a file");
this.removePathButton = this._register(new Button(this.removePathElement.nativeElement)); this.removePathButton = this._register(new Button(this.removePathElement!.nativeElement));
this.removePathButton.label = '-'; this.removePathButton.label = '-';
this.removePathButton.title = localize('removeFile', "Remove files"); this.removePathButton.title = localize('removeFile', "Remove files");
// Set compression // Set compression
this.compressionSelectBox = this._register(new SelectBox(this.compressionOptions, this.compressionOptions[0], this.contextViewService, undefined, { ariaLabel: this.localizedStrings.SET_BACKUP_COMPRESSION })); this.compressionSelectBox = this._register(new SelectBox(this.compressionOptions, this.compressionOptions[0], this.contextViewService, undefined, { ariaLabel: this.localizedStrings.SET_BACKUP_COMPRESSION }));
this.compressionSelectBox.render(this.compressionElement.nativeElement); this.compressionSelectBox.render(this.compressionElement!.nativeElement);
// Set encryption // Set encryption
this.algorithmSelectBox = this._register(new SelectBox(this.encryptionAlgorithms, this.encryptionAlgorithms[0], this.contextViewService, undefined, { ariaLabel: this.localizedStrings.ALGORITHM })); this.algorithmSelectBox = this._register(new SelectBox(this.encryptionAlgorithms, this.encryptionAlgorithms[0], this.contextViewService, undefined, { ariaLabel: this.localizedStrings.ALGORITHM }));
this.algorithmSelectBox.render(this.encryptionAlgorithmElement.nativeElement); this.algorithmSelectBox.render(this.encryptionAlgorithmElement!.nativeElement);
this.encryptorSelectBox = this._register(new SelectBox([], '', this.contextViewService, undefined, { ariaLabel: this.localizedStrings.CERTIFICATE_OR_ASYMMETRIC_KEY })); this.encryptorSelectBox = this._register(new SelectBox([], '', this.contextViewService, undefined, { ariaLabel: this.localizedStrings.CERTIFICATE_OR_ASYMMETRIC_KEY }));
this.encryptorSelectBox.render(this.encryptorElement.nativeElement); this.encryptorSelectBox.render(this.encryptorElement!.nativeElement);
// Set media // Set media
this.mediaNameBox = this._register(new InputBox(this.mediaNameElement.nativeElement, this.mediaNameBox = this._register(new InputBox(this.mediaNameElement!.nativeElement,
this.contextViewService, this.contextViewService,
{ {
validationOptions: { validationOptions: {
@@ -319,13 +321,13 @@ export class BackupComponent extends AngularDisposable {
} }
)); ));
this.mediaDescriptionBox = this._register(new InputBox(this.mediaDescriptionElement.nativeElement, this.contextViewService, { this.mediaDescriptionBox = this._register(new InputBox(this.mediaDescriptionElement!.nativeElement, this.contextViewService, {
ariaLabel: LocalizedStrings.NEW_MEDIA_SET_DESCRIPTION ariaLabel: LocalizedStrings.NEW_MEDIA_SET_DESCRIPTION
})); }));
// Set backup retain days // Set backup retain days
let invalidInputMessage = localize('backupComponent.invalidInput', "Invalid input. Value must be greater than or equal 0."); let invalidInputMessage = localize('backupComponent.invalidInput', "Invalid input. Value must be greater than or equal 0.");
this.backupRetainDaysBox = this._register(new InputBox(this.backupDaysElement.nativeElement, this.backupRetainDaysBox = this._register(new InputBox(this.backupDaysElement!.nativeElement,
this.contextViewService, this.contextViewService,
{ {
placeholder: '0', placeholder: '0',
@@ -362,8 +364,8 @@ export class BackupComponent extends AngularDisposable {
this.backupEnabled = false; this.backupEnabled = false;
// Reset backup values // Reset backup values
this.backupNameBox.value = ''; this.backupNameBox!.value = '';
this.pathListBox.setOptions([], 0); this.pathListBox!.setOptions([], 0);
this.connection = param.connection; this.connection = param.connection;
this._uri = param.ownerUri; this._uri = param.ownerUri;
@@ -387,41 +389,41 @@ export class BackupComponent extends AngularDisposable {
* Show spinner in the backup dialog * Show spinner in the backup dialog
*/ */
private showSpinner(): void { private showSpinner(): void {
this.inProgressElement.nativeElement.style.visibility = 'visible'; this.inProgressElement!.nativeElement.style.visibility = 'visible';
} }
/** /**
* Hide spinner in the backup dialog * Hide spinner in the backup dialog
*/ */
private hideSpinner(): void { private hideSpinner(): void {
this.inProgressElement.nativeElement.style.visibility = 'hidden'; this.inProgressElement!.nativeElement.style.visibility = 'hidden';
} }
private addFooterButtons(): void { private addFooterButtons(): void {
// Set script footer button // Set script footer button
this.scriptButton = this._register(new Button(this.scriptButtonElement.nativeElement)); this.scriptButton = this._register(new Button(this.scriptButtonElement!.nativeElement));
this.scriptButton.label = localize('backupComponent.script', "Script"); this.scriptButton.label = localize('backupComponent.script', "Script");
this.addButtonClickHandler(this.scriptButton, () => this.onScript()); this.scriptButton.onDidClick(() => this.onScript());
this._register(attachButtonStyler(this.scriptButton, this.themeService)); this._register(attachButtonStyler(this.scriptButton, this.themeService));
this.scriptButton.enabled = false; this.scriptButton.enabled = false;
// Set backup footer button // Set backup footer button
this.backupButton = this._register(new Button(this.backupButtonElement.nativeElement)); this.backupButton = this._register(new Button(this.backupButtonElement!.nativeElement));
this.backupButton.label = localize('backupComponent.backup', "Backup"); this.backupButton.label = localize('backupComponent.backup', "Backup");
this.addButtonClickHandler(this.backupButton, () => this.onOk()); this.backupButton.onDidClick(() => this.onOk());
this._register(attachButtonStyler(this.backupButton, this.themeService)); this._register(attachButtonStyler(this.backupButton, this.themeService));
this.backupEnabled = false; this.backupEnabled = false;
// Set cancel footer button // Set cancel footer button
this.cancelButton = this._register(new Button(this.cancelButtonElement.nativeElement)); this.cancelButton = this._register(new Button(this.cancelButtonElement!.nativeElement));
this.cancelButton.label = localize('backupComponent.cancel', "Cancel"); this.cancelButton.label = localize('backupComponent.cancel', "Cancel");
this.addButtonClickHandler(this.cancelButton, () => this.onCancel()); this.cancelButton.onDidClick(() => this.onCancel());
this._register(attachButtonStyler(this.cancelButton, this.themeService)); this._register(attachButtonStyler(this.cancelButton, this.themeService));
} }
private initialize(isMetadataPopulated: boolean): void { private initialize(isMetadataPopulated: boolean): void {
this.databaseName = this.connection.databaseName; this.databaseName = this.connection!.databaseName;
this.selectedBackupComponent = BackupConstants.labelDatabase; this.selectedBackupComponent = BackupConstants.labelDatabase;
this.backupPathTypePairs = {}; this.backupPathTypePairs = {};
this.isFormatChecked = false; this.isFormatChecked = false;
@@ -436,10 +438,10 @@ export class BackupComponent extends AngularDisposable {
this.setControlsForRecoveryModel(); this.setControlsForRecoveryModel();
// Set backup type // Set backup type
this.backupTypeSelectBox.setOptions(this.backupTypeOptions, 0); this.backupTypeSelectBox!.setOptions(this.backupTypeOptions, 0);
this.setDefaultBackupName(); this.setDefaultBackupName();
this.backupNameBox.focus(); this.backupNameBox!.focus();
// Set backup path list // Set backup path list
this.setDefaultBackupPaths(); this.setDefaultBackupPaths();
@@ -447,24 +449,24 @@ export class BackupComponent extends AngularDisposable {
for (let i in this.backupPathTypePairs) { for (let i in this.backupPathTypePairs) {
pathlist.push({ text: i }); pathlist.push({ text: i });
} }
this.pathListBox.setOptions(pathlist, 0); this.pathListBox!.setOptions(pathlist, 0);
// Set encryption // Set encryption
let encryptorItems = this.populateEncryptorCombo(); let encryptorItems = this.populateEncryptorCombo();
this.encryptorSelectBox.setOptions(encryptorItems, 0); this.encryptorSelectBox!.setOptions(encryptorItems, 0);
if (encryptorItems.length === 0) { if (encryptorItems.length === 0) {
// Disable encryption checkbox // Disable encryption checkbox
this.encryptCheckBox.disable(); this.encryptCheckBox!.disable();
// Show warning instead of algorithm select boxes // Show warning instead of algorithm select boxes
(<HTMLElement>this.encryptWarningElement.nativeElement).style.display = 'inline'; (<HTMLElement>this.encryptWarningElement!.nativeElement).style.display = 'inline';
(<HTMLElement>this.encryptContainerElement.nativeElement).style.display = 'none'; (<HTMLElement>this.encryptContainerElement!.nativeElement).style.display = 'none';
} }
else { else {
// Show algorithm select boxes instead of warning // Show algorithm select boxes instead of warning
(<HTMLElement>this.encryptWarningElement.nativeElement).style.display = 'none'; (<HTMLElement>this.encryptWarningElement!.nativeElement).style.display = 'none';
(<HTMLElement>this.encryptContainerElement.nativeElement).style.display = 'inline'; (<HTMLElement>this.encryptContainerElement!.nativeElement).style.display = 'inline';
// Disable the algorithm select boxes since encryption is not checked by default // Disable the algorithm select boxes since encryption is not checked by default
this.setEncryptOptionsEnabled(false); this.setEncryptOptionsEnabled(false);
@@ -473,15 +475,15 @@ export class BackupComponent extends AngularDisposable {
this.setTLogOptions(); this.setTLogOptions();
// disable elements // disable elements
this.recoveryBox.disable(); this.recoveryBox!.disable();
this.mediaNameBox.disable(); this.mediaNameBox!.disable();
this.mediaDescriptionBox.disable(); this.mediaDescriptionBox!.disable();
this.recoveryBox.value = this.recoveryModel; this.recoveryBox!.value = this.recoveryModel!;
// show warning message if latest backup file path contains url // show warning message if latest backup file path contains url
if (this.containsBackupToUrl) { if (this.containsBackupToUrl) {
this.pathListBox.setValidation(false, { content: localize('backup.containsBackupToUrlError', "Only backup to file is supported"), type: MessageType.WARNING }); this.pathListBox!.setValidation(false, { content: localize('backup.containsBackupToUrlError', "Only backup to file is supported"), type: MessageType.WARNING });
this.pathListBox.focus(); this.pathListBox!.focus();
} }
} }
@@ -495,56 +497,56 @@ export class BackupComponent extends AngularDisposable {
this.isFormatChecked = false; this.isFormatChecked = false;
this.isEncryptChecked = false; this.isEncryptChecked = false;
this.copyOnlyCheckBox.checked = false; this.copyOnlyCheckBox!.checked = false;
this.copyOnlyCheckBox.enable(); this.copyOnlyCheckBox!.enable();
this.compressionSelectBox.setOptions(this.compressionOptions, 0); this.compressionSelectBox!.setOptions(this.compressionOptions, 0);
this.encryptCheckBox.checked = false; this.encryptCheckBox!.checked = false;
this.encryptCheckBox.enable(); this.encryptCheckBox!.enable();
this.onChangeEncrypt(); this.onChangeEncrypt();
this.mediaNameBox.value = ''; this.mediaNameBox!.value = '';
this.mediaDescriptionBox.value = ''; this.mediaDescriptionBox!.value = '';
this.checksumCheckBox.checked = false; this.checksumCheckBox!.checked = false;
this.verifyCheckBox.checked = false; this.verifyCheckBox!.checked = false;
this.continueOnErrorCheckBox.checked = false; this.continueOnErrorCheckBox!.checked = false;
this.backupRetainDaysBox.value = '0'; this.backupRetainDaysBox!.value = '0';
this.algorithmSelectBox.setOptions(this.encryptionAlgorithms, 0); this.algorithmSelectBox!.setOptions(this.encryptionAlgorithms, 0);
this.selectedInitOption = this.existingMediaOptions[0]; this.selectedInitOption = this.existingMediaOptions[0];
this.containsBackupToUrl = false; this.containsBackupToUrl = false;
this.pathListBox.setValidation(true); this.pathListBox!.setValidation(true);
this.cancelButton.applyStyles(); this.cancelButton!.applyStyles();
this.scriptButton.applyStyles(); this.scriptButton!.applyStyles();
this.backupButton.applyStyles(); this.backupButton!.applyStyles();
} }
private registerListeners(): void { private registerListeners(): void {
// Theme styler // Theme styler
this._register(attachInputBoxStyler(this.backupNameBox, this.themeService)); this._register(attachInputBoxStyler(this.backupNameBox!, this.themeService));
this._register(attachInputBoxStyler(this.recoveryBox, this.themeService)); this._register(attachInputBoxStyler(this.recoveryBox!, this.themeService));
this._register(attachSelectBoxStyler(this.backupTypeSelectBox, this.themeService)); this._register(attachSelectBoxStyler(this.backupTypeSelectBox!, this.themeService));
this._register(attachListBoxStyler(this.pathListBox, this.themeService)); this._register(attachListBoxStyler(this.pathListBox!, this.themeService));
this._register(attachButtonStyler(this.addPathButton, this.themeService)); this._register(attachButtonStyler(this.addPathButton!, this.themeService));
this._register(attachButtonStyler(this.removePathButton, this.themeService)); this._register(attachButtonStyler(this.removePathButton!, this.themeService));
this._register(attachSelectBoxStyler(this.compressionSelectBox, this.themeService)); this._register(attachSelectBoxStyler(this.compressionSelectBox!, this.themeService));
this._register(attachSelectBoxStyler(this.algorithmSelectBox, this.themeService)); this._register(attachSelectBoxStyler(this.algorithmSelectBox!, this.themeService));
this._register(attachSelectBoxStyler(this.encryptorSelectBox, this.themeService)); this._register(attachSelectBoxStyler(this.encryptorSelectBox!, this.themeService));
this._register(attachInputBoxStyler(this.mediaNameBox, this.themeService)); this._register(attachInputBoxStyler(this.mediaNameBox!, this.themeService));
this._register(attachInputBoxStyler(this.mediaDescriptionBox, this.themeService)); this._register(attachInputBoxStyler(this.mediaDescriptionBox!, this.themeService));
this._register(attachInputBoxStyler(this.backupRetainDaysBox, this.themeService)); this._register(attachInputBoxStyler(this.backupRetainDaysBox!, this.themeService));
this._register(attachCheckboxStyler(this.copyOnlyCheckBox, this.themeService)); this._register(attachCheckboxStyler(this.copyOnlyCheckBox!, this.themeService));
this._register(attachCheckboxStyler(this.encryptCheckBox, this.themeService)); this._register(attachCheckboxStyler(this.encryptCheckBox!, this.themeService));
this._register(attachCheckboxStyler(this.verifyCheckBox, this.themeService)); this._register(attachCheckboxStyler(this.verifyCheckBox!, this.themeService));
this._register(attachCheckboxStyler(this.checksumCheckBox, this.themeService)); this._register(attachCheckboxStyler(this.checksumCheckBox!, this.themeService));
this._register(attachCheckboxStyler(this.continueOnErrorCheckBox, this.themeService)); this._register(attachCheckboxStyler(this.continueOnErrorCheckBox!, this.themeService));
this._register(this.backupTypeSelectBox.onDidSelect(selected => this.onBackupTypeChanged())); this._register(this.backupTypeSelectBox!.onDidSelect(selected => this.onBackupTypeChanged()));
this.addButtonClickHandler(this.addPathButton, () => this.onAddClick()); this.addPathButton!.onDidClick(() => this.onAddClick());
this.addButtonClickHandler(this.removePathButton, () => this.onRemoveClick()); this.removePathButton!.onDidClick(() => this.onRemoveClick());
this._register(this.mediaNameBox.onDidChange(mediaName => { this._register(this.mediaNameBox!.onDidChange(mediaName => {
this.mediaNameChanged(mediaName); this.mediaNameChanged(mediaName);
})); }));
this._register(this.backupRetainDaysBox.onDidChange(days => { this._register(this.backupRetainDaysBox!.onDidChange(days => {
this.backupRetainDaysChanged(days); this.backupRetainDaysChanged(days);
})); }));
@@ -554,43 +556,33 @@ export class BackupComponent extends AngularDisposable {
// Update theming that is specific to backup dialog // Update theming that is specific to backup dialog
private updateTheme(theme: IColorTheme): void { private updateTheme(theme: IColorTheme): void {
// set modal footer style // set modal footer style
let footerHtmlElement: HTMLElement = <HTMLElement>this.modalFooterElement.nativeElement; let footerHtmlElement: HTMLElement = <HTMLElement>this.modalFooterElement!.nativeElement;
const backgroundColor = theme.getColor(SIDE_BAR_BACKGROUND); const backgroundColor = theme.getColor(SIDE_BAR_BACKGROUND);
const border = theme.getColor(cr.contrastBorder) ? theme.getColor(cr.contrastBorder).toString() : null; const border = theme.getColor(cr.contrastBorder)?.toString() ?? '';
const footerBorderTopWidth = border ? '1px' : null; const footerBorderTopWidth = border ? '1px' : '';
const footerBorderTopStyle = border ? 'solid' : null; const footerBorderTopStyle = border ? 'solid' : '';
footerHtmlElement.style.backgroundColor = backgroundColor ? backgroundColor.toString() : null; footerHtmlElement.style.backgroundColor = backgroundColor?.toString() ?? '';
footerHtmlElement.style.borderTopWidth = footerBorderTopWidth; footerHtmlElement.style.borderTopWidth = footerBorderTopWidth;
footerHtmlElement.style.borderTopStyle = footerBorderTopStyle; footerHtmlElement.style.borderTopStyle = footerBorderTopStyle;
footerHtmlElement.style.borderTopColor = border; footerHtmlElement.style.borderTopColor = border;
} }
private addButtonClickHandler(button: Button, handler: () => void) {
if (button && handler) {
button.onDidClick(() => {
if (button.enabled) {
handler();
}
});
}
}
/* /*
* UI event handlers * UI event handlers
*/ */
private onScript(): void { private onScript(): void {
this._backupService.backup(this._uri, this.createBackupInfo(), TaskExecutionMode.script); this._backupService.backup(this._uri!, this.createBackupInfo(), TaskExecutionMode.script);
this.close(); this.close();
} }
private onOk(): void { private onOk(): void {
this._backupService.backup(this._uri, this.createBackupInfo(), TaskExecutionMode.executeAndScript); this._backupService.backup(this._uri!, this.createBackupInfo(), TaskExecutionMode.executeAndScript);
this.close(); this.close();
} }
private onCancel(): void { private onCancel(): void {
this.close(); this.close();
this.connectionManagementService.disconnect(this._uri); this.connectionManagementService.disconnect(this._uri!);
} }
private close(): void { private close(): void {
@@ -605,7 +597,7 @@ export class BackupComponent extends AngularDisposable {
} }
private onChangeEncrypt(): void { private onChangeEncrypt(): void {
if (this.encryptCheckBox.checked) { if (this.encryptCheckBox!.checked) {
this.setEncryptOptionsEnabled(true); this.setEncryptOptionsEnabled(true);
// Force to choose format media option since otherwise encryption cannot be done // Force to choose format media option since otherwise encryption cannot be done
@@ -615,7 +607,7 @@ export class BackupComponent extends AngularDisposable {
} else { } else {
this.setEncryptOptionsEnabled(false); this.setEncryptOptionsEnabled(false);
} }
this.isEncryptChecked = this.encryptCheckBox.checked; this.isEncryptChecked = this.encryptCheckBox!.checked;
this.detectChange(); this.detectChange();
} }
@@ -623,10 +615,10 @@ export class BackupComponent extends AngularDisposable {
this.isFormatChecked = !this.isFormatChecked; this.isFormatChecked = !this.isFormatChecked;
this.enableMediaInput(this.isFormatChecked); this.enableMediaInput(this.isFormatChecked);
if (this.isFormatChecked) { if (this.isFormatChecked) {
if (strings.isFalsyOrWhitespace(this.mediaNameBox.value)) { if (strings.isFalsyOrWhitespace(this.mediaNameBox!.value)) {
this.backupEnabled = false; this.backupEnabled = false;
this.backupButton.enabled = false; this.backupButton!.enabled = false;
this.mediaNameBox.showMessage({ type: MessageType.ERROR, content: LocalizedStrings.MEDIA_NAME_REQUIRED_ERROR }); this.mediaNameBox!.showMessage({ type: MessageType.ERROR, content: LocalizedStrings.MEDIA_NAME_REQUIRED_ERROR });
} }
} else { } else {
this.enableBackupButton(); this.enableBackupButton();
@@ -635,16 +627,16 @@ export class BackupComponent extends AngularDisposable {
} }
private set backupEnabled(value: boolean) { private set backupEnabled(value: boolean) {
this.backupButton.enabled = value; this.backupButton!.enabled = value;
this.scriptButton.enabled = value; this.scriptButton!.enabled = value;
} }
private onBackupTypeChanged(): void { private onBackupTypeChanged(): void {
if (this.getSelectedBackupType() === BackupConstants.labelDifferential) { if (this.getSelectedBackupType() === BackupConstants.labelDifferential) {
this.copyOnlyCheckBox.checked = false; this.copyOnlyCheckBox!.checked = false;
this.copyOnlyCheckBox.disable(); this.copyOnlyCheckBox!.disable();
} else { } else {
this.copyOnlyCheckBox.enable(); this.copyOnlyCheckBox!.enable();
} }
this.setTLogOptions(); this.setTLogOptions();
@@ -653,8 +645,8 @@ export class BackupComponent extends AngularDisposable {
} }
private onAddClick(): void { private onAddClick(): void {
this.fileBrowserDialogService.showDialog(this._uri, this.fileBrowserDialogService.showDialog(this._uri!,
this.defaultNewBackupFolder, this.defaultNewBackupFolder!,
fileFiltersSet, fileFiltersSet,
FileValidationConstants.backup, FileValidationConstants.backup,
false, false,
@@ -662,16 +654,16 @@ export class BackupComponent extends AngularDisposable {
} }
private handlePathAdded(filepath: string) { private handlePathAdded(filepath: string) {
if (filepath && !this.backupPathTypePairs[filepath]) { if (filepath && !this.backupPathTypePairs![filepath]) {
if ((this.getBackupPathCount() < BackupConstants.maxDevices)) { if ((this.getBackupPathCount() < BackupConstants.maxDevices)) {
this.backupPathTypePairs[filepath] = BackupConstants.deviceTypeFile; this.backupPathTypePairs![filepath] = BackupConstants.deviceTypeFile;
this.pathListBox.add(filepath); this.pathListBox!.add(filepath);
this.enableBackupButton(); this.enableBackupButton();
this.enableAddRemoveButtons(); this.enableAddRemoveButtons();
// stop showing error message if the list content was invalid due to no file path // stop showing error message if the list content was invalid due to no file path
if (!this.pathListBox.isContentValid && this.pathListBox.count === 1) { if (!this.pathListBox!.isContentValid && this.pathListBox!.count === 1) {
this.pathListBox.setValidation(true); this.pathListBox!.setValidation(true);
} }
this._changeDetectorRef.detectChanges(); this._changeDetectorRef.detectChanges();
@@ -680,26 +672,25 @@ export class BackupComponent extends AngularDisposable {
} }
private onRemoveClick(): void { private onRemoveClick(): void {
let self = this; this.pathListBox!.selectedOptions.forEach(selected => {
this.pathListBox.selectedOptions.forEach(selected => { if (this.backupPathTypePairs![selected]) {
if (self.backupPathTypePairs[selected]) { if (this.backupPathTypePairs![selected] === BackupConstants.deviceTypeURL) {
if (self.backupPathTypePairs[selected] === BackupConstants.deviceTypeURL) {
// stop showing warning message since url path is getting removed // stop showing warning message since url path is getting removed
this.pathListBox.setValidation(true); this.pathListBox!.setValidation(true);
this.containsBackupToUrl = false; this.containsBackupToUrl = false;
} }
delete self.backupPathTypePairs[selected]; delete this.backupPathTypePairs![selected];
} }
}); });
this.pathListBox.remove(); this.pathListBox!.remove();
if (this.pathListBox.count === 0) { if (this.pathListBox!.count === 0) {
this.backupEnabled = false; this.backupEnabled = false;
// show input validation error // show input validation error
this.pathListBox.setValidation(false, { content: localize('backup.backupFileRequired', "Backup file path is required"), type: MessageType.ERROR }); this.pathListBox!.setValidation(false, { content: localize('backup.backupFileRequired', "Backup file path is required"), type: MessageType.ERROR });
this.pathListBox.focus(); this.pathListBox!.focus();
} }
this.enableAddRemoveButtons(); this.enableAddRemoveButtons();
@@ -707,13 +698,13 @@ export class BackupComponent extends AngularDisposable {
} }
private enableAddRemoveButtons(): void { private enableAddRemoveButtons(): void {
if (this.pathListBox.count === 0) { if (this.pathListBox!.count === 0) {
this.removePathButton.enabled = false; this.removePathButton!.enabled = false;
} else if (this.pathListBox.count === BackupConstants.maxDevices) { } else if (this.pathListBox!.count === BackupConstants.maxDevices) {
this.addPathButton.enabled = false; this.addPathButton!.enabled = false;
} else { } else {
this.removePathButton.enabled = true; this.removePathButton!.enabled = true;
this.addPathButton.enabled = true; this.addPathButton!.enabled = true;
} }
} }
@@ -729,18 +720,18 @@ export class BackupComponent extends AngularDisposable {
} }
private populateBackupTypes(): void { private populateBackupTypes(): void {
this.backupTypeOptions.push(BackupConstants.labelFull); this.backupTypeOptions!.push(BackupConstants.labelFull);
if (this.databaseName !== 'master') { if (this.databaseName !== 'master') {
this.backupTypeOptions.push(BackupConstants.labelDifferential); this.backupTypeOptions!.push(BackupConstants.labelDifferential);
if (this.recoveryModel !== BackupConstants.recoveryModelSimple) { if (this.recoveryModel !== BackupConstants.recoveryModelSimple) {
this.backupTypeOptions.push(BackupConstants.labelLog); this.backupTypeOptions!.push(BackupConstants.labelLog);
} }
} }
} }
private populateEncryptorCombo(): string[] { private populateEncryptorCombo(): string[] {
let encryptorCombo = []; let encryptorCombo: string[] = [];
this.backupEncryptors.forEach((encryptor) => { this.backupEncryptors!.forEach((encryptor) => {
let encryptorTypeStr = (encryptor.encryptorType === 0 ? BackupConstants.serverCertificate : BackupConstants.asymmetricKey); let encryptorTypeStr = (encryptor.encryptorType === 0 ? BackupConstants.serverCertificate : BackupConstants.asymmetricKey);
encryptorCombo.push(encryptor.encryptorName + '(' + encryptorTypeStr + ')'); encryptorCombo.push(encryptor.encryptorName + '(' + encryptorTypeStr + ')');
}); });
@@ -767,17 +758,17 @@ export class BackupComponent extends AngularDisposable {
let defaultNewBackupLocation = this.defaultNewBackupFolder + serverPathSeparator + this.databaseName + formattedDateTime + '.bak'; let defaultNewBackupLocation = this.defaultNewBackupFolder + serverPathSeparator + this.databaseName + formattedDateTime + '.bak';
// Add a default new backup location // Add a default new backup location
this.backupPathTypePairs[defaultNewBackupLocation] = BackupConstants.deviceTypeFile; this.backupPathTypePairs![defaultNewBackupLocation] = BackupConstants.deviceTypeFile;
} }
} }
private enableMediaInput(enable: boolean): void { private enableMediaInput(enable: boolean): void {
if (enable) { if (enable) {
this.mediaNameBox.enable(); this.mediaNameBox!.enable();
this.mediaDescriptionBox.enable(); this.mediaDescriptionBox!.enable();
} else { } else {
this.mediaNameBox.disable(); this.mediaNameBox!.disable();
this.mediaDescriptionBox.disable(); this.mediaDescriptionBox!.disable();
} }
} }
@@ -801,7 +792,7 @@ export class BackupComponent extends AngularDisposable {
} }
private getBackupTypeNumber(): number { private getBackupTypeNumber(): number {
let backupType; let backupType: number;
switch (this.getSelectedBackupType()) { switch (this.getSelectedBackupType()) {
case BackupConstants.labelFull: case BackupConstants.labelFull:
backupType = 0; backupType = 0;
@@ -813,11 +804,11 @@ export class BackupComponent extends AngularDisposable {
backupType = 2; backupType = 2;
break; break;
} }
return backupType; return backupType!;
} }
private getBackupPathCount(): number { private getBackupPathCount(): number {
return this.pathListBox.count; return this.pathListBox!.count;
} }
private getSelectedBackupType(): string { private getSelectedBackupType(): string {
@@ -829,8 +820,8 @@ export class BackupComponent extends AngularDisposable {
} }
private enableBackupButton(): void { private enableBackupButton(): void {
if (!this.backupButton.enabled) { if (!this.backupButton!.enabled) {
if (this.pathListBox.count > 0 && (!this.isFormatChecked || this.mediaNameBox.value) && this.backupRetainDaysBox.validate()) { if (this.pathListBox!.count > 0 && (!this.isFormatChecked || this.mediaNameBox!.value) && this.backupRetainDaysBox!.validate()) {
this.backupEnabled = true; this.backupEnabled = true;
} }
} }
@@ -838,11 +829,11 @@ export class BackupComponent extends AngularDisposable {
private setEncryptOptionsEnabled(enabled: boolean): void { private setEncryptOptionsEnabled(enabled: boolean): void {
if (enabled) { if (enabled) {
this.algorithmSelectBox.enable(); this.algorithmSelectBox!.enable();
this.encryptorSelectBox.enable(); this.encryptorSelectBox!.enable();
} else { } else {
this.algorithmSelectBox.disable(); this.algorithmSelectBox!.disable();
this.encryptorSelectBox.disable(); this.encryptorSelectBox!.disable();
} }
} }
@@ -855,7 +846,7 @@ export class BackupComponent extends AngularDisposable {
} }
private backupRetainDaysChanged(days: string): void { private backupRetainDaysChanged(days: string): void {
if (!this.backupRetainDaysBox.validate()) { if (!this.backupRetainDaysBox!.validate()) {
this.backupEnabled = false; this.backupEnabled = false;
} else { } else {
this.enableBackupButton(); this.enableBackupButton();
@@ -863,49 +854,49 @@ export class BackupComponent extends AngularDisposable {
} }
private createBackupInfo(): MssqlBackupInfo { private createBackupInfo(): MssqlBackupInfo {
let backupPathArray = []; let backupPathArray: string[] = [];
for (let i in this.backupPathTypePairs) { for (let i in this.backupPathTypePairs) {
backupPathArray.push(i); backupPathArray.push(i);
} }
// get encryptor type and name // get encryptor type and name
let encryptorName = ''; let encryptorName = '';
let encryptorType; let encryptorType: number | undefined;
if (this.encryptCheckBox.checked && this.encryptorSelectBox.value !== '') { if (this.encryptCheckBox!.checked && this.encryptorSelectBox!.value !== '') {
let selectedEncryptor = this.encryptorSelectBox.value; let selectedEncryptor = this.encryptorSelectBox!.value;
let encryptorTypeStr = selectedEncryptor.substring(selectedEncryptor.lastIndexOf('(') + 1, selectedEncryptor.lastIndexOf(')')); let encryptorTypeStr = selectedEncryptor.substring(selectedEncryptor.lastIndexOf('(') + 1, selectedEncryptor.lastIndexOf(')'));
encryptorType = (encryptorTypeStr === BackupConstants.serverCertificate ? 0 : 1); encryptorType = (encryptorTypeStr === BackupConstants.serverCertificate ? 0 : 1);
encryptorName = selectedEncryptor.substring(0, selectedEncryptor.lastIndexOf('(')); encryptorName = selectedEncryptor.substring(0, selectedEncryptor.lastIndexOf('('));
} }
let backupInfo = <MssqlBackupInfo>{ let backupInfo = {
ownerUri: this._uri, ownerUri: this._uri!,
databaseName: this.databaseName, databaseName: this.databaseName!,
backupType: this.getBackupTypeNumber(), backupType: this.getBackupTypeNumber(),
backupComponent: 0, backupComponent: 0,
backupDeviceType: BackupConstants.backupDeviceTypeDisk, backupDeviceType: BackupConstants.backupDeviceTypeDisk,
backupPathList: backupPathArray, backupPathList: backupPathArray,
selectedFiles: this.selectedFilesText, selectedFiles: this.selectedFilesText!,
backupsetName: this.backupNameBox.value, backupsetName: this.backupNameBox!.value,
selectedFileGroup: undefined, selectedFileGroup: undefined,
backupPathDevices: this.backupPathTypePairs, backupPathDevices: this.backupPathTypePairs!,
isCopyOnly: this.copyOnlyCheckBox.checked, isCopyOnly: this.copyOnlyCheckBox!.checked,
// Get advanced options // Get advanced options
formatMedia: this.isFormatChecked, formatMedia: this.isFormatChecked!,
initialize: (this.isFormatChecked ? true : (this.selectedInitOption === this.existingMediaOptions[1])), initialize: (this.isFormatChecked ? true : (this.selectedInitOption === this.existingMediaOptions[1])),
skipTapeHeader: this.isFormatChecked, skipTapeHeader: this.isFormatChecked!,
mediaName: (this.isFormatChecked ? this.mediaNameBox.value : ''), mediaName: (this.isFormatChecked ? this.mediaNameBox!.value : ''),
mediaDescription: (this.isFormatChecked ? this.mediaDescriptionBox.value : ''), mediaDescription: (this.isFormatChecked ? this.mediaDescriptionBox!.value : ''),
checksum: this.checksumCheckBox.checked, checksum: this.checksumCheckBox!.checked,
continueAfterError: this.continueOnErrorCheckBox.checked, continueAfterError: this.continueOnErrorCheckBox!.checked,
logTruncation: this.isTruncateChecked, logTruncation: this.isTruncateChecked!,
tailLogBackup: this.isTaillogChecked, tailLogBackup: this.isTaillogChecked!,
retainDays: strings.isFalsyOrWhitespace(this.backupRetainDaysBox.value) ? 0 : this.backupRetainDaysBox.value, retainDays: strings.isFalsyOrWhitespace(this.backupRetainDaysBox!.value) ? 0 : Number(this.backupRetainDaysBox!.value),
compressionOption: this.compressionOptions.indexOf(this.compressionSelectBox.value), compressionOption: this.compressionOptions.indexOf(this.compressionSelectBox!.value),
verifyBackupRequired: this.verifyCheckBox.checked, verifyBackupRequired: this.verifyCheckBox!.checked,
encryptionAlgorithm: (this.encryptCheckBox.checked ? this.encryptionAlgorithms.indexOf(this.algorithmSelectBox.value) : 0), encryptionAlgorithm: (this.encryptCheckBox!.checked ? this.encryptionAlgorithms.indexOf(this.algorithmSelectBox!.value) : 0),
encryptorType: encryptorType, encryptorType: encryptorType,
encryptorName: encryptorName encryptorName: encryptorName
}; };

View File

@@ -27,9 +27,11 @@ new BackupAction().registerTask();
const DE_BACKUP_COMMAND_ID = 'dataExplorer.backup'; const DE_BACKUP_COMMAND_ID = 'dataExplorer.backup';
CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({
id: DE_BACKUP_COMMAND_ID, id: DE_BACKUP_COMMAND_ID,
handler: (accessor, args: TreeViewItemHandleArg) => { handler: async (accessor, args: TreeViewItemHandleArg) => {
const commandService = accessor.get(ICommandService); if (args.$treeItem?.payload) {
return commandService.executeCommand(BackupAction.ID, args.$treeItem.payload); const commandService = accessor.get(ICommandService);
return commandService.executeCommand(BackupAction.ID, args.$treeItem.payload);
}
} }
}); });

View File

@@ -39,9 +39,9 @@ export class BackupAction extends Task {
}); });
} }
runTask(accessor: ServicesAccessor, profile: IConnectionProfile): void | Promise<void> { runTask(accessor: ServicesAccessor, profile?: IConnectionProfile): void | Promise<void> {
const configurationService = accessor.get<IConfigurationService>(IConfigurationService); const configurationService = accessor.get<IConfigurationService>(IConfigurationService);
const previewFeaturesEnabled: boolean = configurationService.getValue('workbench')['enablePreviewFeatures']; const previewFeaturesEnabled = configurationService.getValue<{ enablePreviewFeatures: boolean }>('workbench').enablePreviewFeatures;
if (!previewFeaturesEnabled) { if (!previewFeaturesEnabled) {
return accessor.get<INotificationService>(INotificationService).info(localize('backup.isPreviewFeature', "You must enable preview features in order to use backup")); return accessor.get<INotificationService>(INotificationService).info(localize('backup.isPreviewFeature', "You must enable preview features in order to use backup"));
} }

View File

@@ -20,11 +20,12 @@ import { ITextResourcePropertiesService } from 'vs/editor/common/services/textRe
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry'; import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
import { attachModalDialogStyler } from 'sql/workbench/common/styler'; import { attachModalDialogStyler } from 'sql/workbench/common/styler';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
import { NgModuleRef } from '@angular/core';
export class BackupDialog extends Modal { export class BackupDialog extends Modal {
private _body: HTMLElement; private _body?: HTMLElement;
private _backupTitle: string; private _backupTitle?: string;
private _moduleRef: any; private _moduleRef?: NgModuleRef<typeof BackupModule>;
constructor( constructor(
@IThemeService themeService: IThemeService, @IThemeService themeService: IThemeService,
@@ -48,7 +49,7 @@ export class BackupDialog extends Modal {
attachModalDialogStyler(this, this._themeService); attachModalDialogStyler(this, this._themeService);
// Add angular component template to dialog body // Add angular component template to dialog body
this.bootstrapAngular(this._body); this.bootstrapAngular(this._body!);
} }
/** /**
@@ -61,7 +62,7 @@ export class BackupDialog extends Modal {
BACKUP_SELECTOR, BACKUP_SELECTOR,
undefined, undefined,
undefined, undefined,
(moduleRef) => this._moduleRef = moduleRef); (moduleRef: NgModuleRef<typeof BackupModule>) => this._moduleRef = moduleRef);
} }
public hideError() { public hideError() {

View File

@@ -17,14 +17,13 @@ import { BackupDialog } from 'sql/workbench/contrib/backup/browser/backupDialog'
import { OptionsDialog } from 'sql/workbench/browser/modal/optionsDialog'; import { OptionsDialog } from 'sql/workbench/browser/modal/optionsDialog';
import { IBackupService, TaskExecutionMode } from 'sql/platform/backup/common/backupService'; import { IBackupService, TaskExecutionMode } from 'sql/platform/backup/common/backupService';
import { IBackupUiService } from 'sql/workbench/contrib/backup/common/backupUiService'; import { IBackupUiService } from 'sql/workbench/contrib/backup/common/backupUiService';
import { find } from 'vs/base/common/arrays';
export class BackupUiService implements IBackupUiService { export class BackupUiService implements IBackupUiService {
public _serviceBrand: undefined; public _serviceBrand: undefined;
private _backupDialogs: { [providerName: string]: BackupDialog | OptionsDialog } = {}; private _backupDialogs: { [providerName: string]: BackupDialog | OptionsDialog } = {};
private _currentProvider: string; private _currentProvider?: string;
private _optionValues: { [optionName: string]: any } = {}; private _optionValues: { [optionName: string]: any } = {};
private _connectionUri: string; private _connectionUri?: string;
private static _connectionUniqueId: number = 0; private static _connectionUniqueId: number = 0;
private _onShowBackupEvent: Emitter<{ connection: IConnectionProfile, ownerUri: string }>; private _onShowBackupEvent: Emitter<{ connection: IConnectionProfile, ownerUri: string }>;
@@ -50,8 +49,8 @@ export class BackupUiService implements IBackupUiService {
}); });
} }
private getOptions(provider: string): azdata.ServiceOption[] { private getOptions(provider: string): azdata.ServiceOption[] | undefined {
let feature = find(this._capabilitiesService.getLegacyCapabilities(this._currentProvider).features, f => f.featureName === 'backup'); let feature = this._capabilitiesService.getLegacyCapabilities(provider)?.features.find(f => f.featureName === 'backup');
if (feature) { if (feature) {
return feature.optionsMetadata; return feature.optionsMetadata;
} else { } else {
@@ -60,22 +59,21 @@ export class BackupUiService implements IBackupUiService {
} }
public async showBackupDialog(connection: IConnectionProfile): Promise<void> { public async showBackupDialog(connection: IConnectionProfile): Promise<void> {
let self = this; this._connectionUri = ConnectionUtils.generateUri(connection);
self._connectionUri = ConnectionUtils.generateUri(connection); this._currentProvider = connection.providerName;
self._currentProvider = connection.providerName; let backupDialog = this._backupDialogs[this._currentProvider];
let backupDialog = self._backupDialogs[self._currentProvider];
if (!backupDialog) { if (!backupDialog) {
let backupOptions = this.getOptions(this._currentProvider); let backupOptions = this.getOptions(this._currentProvider);
if (backupOptions) { if (backupOptions) {
backupDialog = self._instantiationService ? self._instantiationService.createInstance( backupDialog = this._instantiationService.createInstance(
OptionsDialog, 'Backup database - ' + connection.serverName + ':' + connection.databaseName, 'BackupOptions', undefined) : undefined; OptionsDialog, 'Backup database - ' + connection.serverName + ':' + connection.databaseName, 'BackupOptions', undefined);
backupDialog.onOk(() => this.handleOptionDialogClosed()); backupDialog.onOk(() => this.handleOptionDialogClosed());
} }
else { else {
backupDialog = self._instantiationService ? self._instantiationService.createInstance(BackupDialog) : undefined; backupDialog = this._instantiationService.createInstance(BackupDialog);
} }
backupDialog.render(); backupDialog.render();
self._backupDialogs[self._currentProvider] = backupDialog; this._backupDialogs[this._currentProvider] = backupDialog;
} }
let backupOptions = this.getOptions(this._currentProvider); let backupOptions = this.getOptions(this._currentProvider);
@@ -90,7 +88,7 @@ export class BackupUiService implements IBackupUiService {
BackupUiService._connectionUniqueId++; BackupUiService._connectionUniqueId++;
if (backupOptions) { if (backupOptions) {
(backupDialog as OptionsDialog).open(backupOptions, self._optionValues); (backupDialog as OptionsDialog).open(backupOptions, this._optionValues);
} else { } else {
(backupDialog as BackupDialog).open(connection); (backupDialog as BackupDialog).open(connection);
} }
@@ -103,22 +101,25 @@ export class BackupUiService implements IBackupUiService {
} }
public onShowBackupDialog() { public onShowBackupDialog() {
let backupDialog = this._backupDialogs[this._currentProvider]; if (this._currentProvider) {
if (backupDialog) { let backupDialog = this._backupDialogs[this._currentProvider];
backupDialog.setInitialFocusedElement(); if (backupDialog) {
backupDialog.setInitialFocusedElement();
}
} }
} }
public closeBackup() { public closeBackup() {
let self = this; if (this._currentProvider) {
let backupDialog = self._backupDialogs[self._currentProvider]; let backupDialog = this._backupDialogs[this._currentProvider];
if (backupDialog) { if (backupDialog) {
backupDialog.close(); backupDialog.close();
}
} }
} }
private handleOptionDialogClosed() { private handleOptionDialogClosed() {
this._disasterRecoveryService.backup(this._connectionUri, this._optionValues, TaskExecutionMode.executeAndScript); this._disasterRecoveryService.backup(this._connectionUri!, this._optionValues, TaskExecutionMode.executeAndScript);
} }
} }

View File

@@ -26,10 +26,10 @@ export interface IBackupUiService {
/** /**
* Close backup wizard * Close backup wizard
*/ */
closeBackup(); closeBackup(): void;
/** /**
* After the backup dialog is rendered, run Modal methods to set focusable elements, etc. * After the backup dialog is rendered, run Modal methods to set focusable elements, etc.
*/ */
onShowBackupDialog(); onShowBackupDialog(): void;
} }

View File

@@ -58,7 +58,6 @@
"./sql/workbench/api/common/**/*.ts", // 300 errors "./sql/workbench/api/common/**/*.ts", // 300 errors
"./sql/workbench/browser/**/*.ts", // 2988 errors "./sql/workbench/browser/**/*.ts", // 2988 errors
"./sql/workbench/contrib/assessment/**/*.ts", // 2990 errors "./sql/workbench/contrib/assessment/**/*.ts", // 2990 errors
"./sql/workbench/contrib/backup/**/*.ts", // 89 errors
"./sql/workbench/contrib/charts/**/*.ts", // 2988 errors "./sql/workbench/contrib/charts/**/*.ts", // 2988 errors
"./sql/workbench/contrib/commandLine/**/*.ts", // 3014 errors "./sql/workbench/contrib/commandLine/**/*.ts", // 3014 errors
"./sql/workbench/contrib/connection/**/*.ts", // 244 errors "./sql/workbench/contrib/connection/**/*.ts", // 244 errors