diff --git a/src/sql/platform/dialog/dialogModal.ts b/src/sql/platform/dialog/dialogModal.ts index 2b6966ffef..270daf326b 100644 --- a/src/sql/platform/dialog/dialogModal.ts +++ b/src/sql/platform/dialog/dialogModal.ts @@ -125,11 +125,19 @@ export class DialogModal extends Modal { public async done(): Promise { if (this._doneButton.enabled) { + let buttonSpinnerHandler = setTimeout(() => { + this._doneButton.enabled = false; + this._doneButton.element.innerHTML = ' '; + this._doneButton.element.classList.add('validating'); + }, 100); if (await this._dialog.validateClose()) { this._onDone.fire(); this.dispose(); this.hide(); } + clearTimeout(buttonSpinnerHandler); + this._doneButton.element.classList.remove('validating'); + this.updateButtonElement(this._doneButton, this._dialog.okButton, true); } } diff --git a/src/sql/platform/dialog/media/dialogModal.css b/src/sql/platform/dialog/media/dialogModal.css index 0d5dc54bdf..ca4034d7a3 100644 --- a/src/sql/platform/dialog/media/dialogModal.css +++ b/src/sql/platform/dialog/media/dialogModal.css @@ -31,6 +31,21 @@ margin: 0; } +.footer-button .validating { + background-size: 15px; + background-repeat: no-repeat; + background-position: center; +} + +.vs .footer-button .validating { + background-image: url("loading.svg"); +} + +.vs-dark .footer-button .validating, +.hc-black .footer-button .validating { + background-image: url("loading_inverse.svg"); +} + .dialogModal-wizardHeader { padding: 10px 30px; } diff --git a/src/sql/platform/dialog/media/loading.svg b/src/sql/platform/dialog/media/loading.svg new file mode 100644 index 0000000000..e762f06d5e --- /dev/null +++ b/src/sql/platform/dialog/media/loading.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/src/sql/platform/dialog/media/loading_inverse.svg b/src/sql/platform/dialog/media/loading_inverse.svg new file mode 100644 index 0000000000..c3633c0dda --- /dev/null +++ b/src/sql/platform/dialog/media/loading_inverse.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/src/sql/platform/dialog/wizardModal.ts b/src/sql/platform/dialog/wizardModal.ts index 2b37b22223..ba9777406f 100644 --- a/src/sql/platform/dialog/wizardModal.ts +++ b/src/sql/platform/dialog/wizardModal.ts @@ -120,6 +120,7 @@ export class WizardModal extends Modal { buttonElement.label = dialogButton.label; buttonElement.enabled = requirePageValid ? dialogButton.enabled && this._wizard.pages[this._wizard.currentPage].valid : dialogButton.enabled; dialogButton.hidden ? buttonElement.element.parentElement.classList.add('dialogModal-hidden') : buttonElement.element.parentElement.classList.remove('dialogModal-hidden'); + this.setButtonsForPage(this._wizard.currentPage); } protected renderBody(container: HTMLElement): void { @@ -167,7 +168,7 @@ export class WizardModal extends Modal { this.done(validate); return; } - if (validate && !await this._wizard.validateNavigation(index)) { + if (validate && !await this.validateNavigation(index)) { return; } this._dialogPanes.forEach((dialogPane, page) => { @@ -185,20 +186,24 @@ export class WizardModal extends Modal { } private setButtonsForPage(index: number) { - if (this._wizard.pages[index - 1]) { - this._previousButton.element.parentElement.classList.remove('dialogModal-hidden'); - this._previousButton.enabled = this._wizard.pages[index - 1].enabled; - } else { - this._previousButton.element.parentElement.classList.add('dialogModal-hidden'); + if (this._previousButton) { + if (this._wizard.pages[index - 1]) { + this._previousButton.element.parentElement.classList.remove('dialogModal-hidden'); + this._previousButton.enabled = this._wizard.pages[index - 1].enabled; + } else { + this._previousButton.element.parentElement.classList.add('dialogModal-hidden'); + } } - if (this._wizard.pages[index + 1]) { - this._nextButton.element.parentElement.classList.remove('dialogModal-hidden'); - this._nextButton.enabled = this._wizard.pages[index + 1].enabled; - this._doneButton.element.parentElement.classList.add('dialogModal-hidden'); - } else { - this._nextButton.element.parentElement.classList.add('dialogModal-hidden'); - this._doneButton.element.parentElement.classList.remove('dialogModal-hidden'); + if (this._nextButton && this._doneButton) { + if (this._wizard.pages[index + 1]) { + this._nextButton.element.parentElement.classList.remove('dialogModal-hidden'); + this._nextButton.enabled = this._wizard.pages[index + 1].enabled; + this._doneButton.element.parentElement.classList.add('dialogModal-hidden'); + } else { + this._nextButton.element.parentElement.classList.add('dialogModal-hidden'); + this._doneButton.element.parentElement.classList.remove('dialogModal-hidden'); + } } } @@ -225,7 +230,7 @@ export class WizardModal extends Modal { public async done(validate: boolean = true): Promise { if (this._doneButton.enabled) { - if (validate && !await this._wizard.validateNavigation(undefined)) { + if (validate && !await this.validateNavigation(undefined)) { return; } this._onDone.fire(); @@ -240,6 +245,20 @@ export class WizardModal extends Modal { this.hide(); } + private async validateNavigation(newPage: number): Promise { + let button = newPage === undefined ? this._doneButton : this._nextButton; + let buttonSpinnerHandler = setTimeout(() => { + button.enabled = false; + button.element.innerHTML = ' '; + button.element.classList.add('validating'); + }, 100); + let navigationValid = await this._wizard.validateNavigation(newPage); + clearTimeout(buttonSpinnerHandler); + button.element.classList.remove('validating'); + this.updateButtonElement(button, newPage === undefined ? this._wizard.doneButton : this._wizard.nextButton, true); + return navigationValid; + } + protected hide(): void { super.hide(); } diff --git a/src/sql/workbench/api/node/extHostModelViewDialog.ts b/src/sql/workbench/api/node/extHostModelViewDialog.ts index 428e0a7883..4fee53d9f0 100644 --- a/src/sql/workbench/api/node/extHostModelViewDialog.ts +++ b/src/sql/workbench/api/node/extHostModelViewDialog.ts @@ -213,12 +213,16 @@ class BackgroundOperationHandler { } public createOperation(): void { + if (!this._operationInfo) { + return; + } + if (!this._operationInfo.operationId) { let uniqueId = generateUuid(); this._operationInfo.operationId = 'OperationId' + uniqueId + this._name; } - if (this._operationInfo && this._operationInfo.operation) { + if (this._operationInfo.operation) { this._extHostTaskManagement.$registerTask(this._operationInfo); } }