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