/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as azdata from 'azdata'; import * as vscode from 'vscode'; import * as localizedConstants from './localizedConstants'; import { DialogBase } from './dialogBase'; import { getErrorMessage } from '../utils'; import { providerId } from '../constants'; export interface ScriptableDialogOptions { /** * The width of the dialog, defaults to narrow if not set */ width?: azdata.window.DialogWidth; /** * The object explorer context in which this dialog was opened. */ objectExplorerContext?: azdata.ObjectExplorerContext; } /** * Base class for a scriptable dialog - that is a dialog that has a "Script" button which will * open a new editor with the generated script when clicked. This also includes a "Help" button * to open up a given URL when clicked. */ export abstract class ScriptableDialogBase extends DialogBase { private _helpButton: azdata.window.Button; private _scriptButton: azdata.window.Button; constructor(title: string, name: string, protected readonly options: OptionsType) { super(title, name, options.width || 'narrow', 'flyout' ); this._helpButton = azdata.window.createButton(localizedConstants.HelpText, 'left'); this.disposables.push(this._helpButton.onClick(async () => { await vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(this.helpUrl)); })); this._scriptButton = azdata.window.createButton(localizedConstants.ScriptText, 'left'); this.disposables.push(this._scriptButton.onClick(async () => { await this.onScriptButtonClick(); })); this.dialogObject.customButtons = [this._helpButton, this._scriptButton]; } /** * Called after initializeData to initialize the UI components of the dialog. */ protected abstract initializeUI(): Promise; /** * Called before initializeUI to initialize the data for the dialog. */ protected abstract initializeData(): Promise; /** * The URL to open when the Help button is clicked */ protected abstract get helpUrl(): string; /** * Whether the dialog is currently dirty, which will control what buttons are enabled. */ protected abstract get isDirty(): boolean; protected override onFormFieldChange(): void { this._scriptButton.enabled = this.isDirty; this.dialogObject.okButton.enabled = this.isDirty; } protected override async initialize(): Promise { await this.initializeData(); await this.initializeUI(); } protected override updateLoadingStatus(isLoading: boolean, loadingText?: string, loadingCompletedText?: string): void { super.updateLoadingStatus(isLoading, loadingText, loadingCompletedText); this._helpButton.enabled = !isLoading; this.dialogObject.okButton.enabled = this._scriptButton.enabled = isLoading ? false : this.isDirty; } /** * Called when the script button is clicked, returns the script that will be opened up in a new editor. */ protected abstract generateScript(): Promise; private async onScriptButtonClick(): Promise { this.updateLoadingStatus(true, localizedConstants.GeneratingScriptText, localizedConstants.GeneratingScriptCompletedText); try { const isValid = await this.runValidation(); if (!isValid) { return; } let message: string; const script = await this.generateScript(); if (script) { message = localizedConstants.ScriptGeneratedText; let doc = await azdata.queryeditor.openQueryDocument({ content: script }, providerId); if (this.options.objectExplorerContext?.connectionProfile) { let profile = this.options.objectExplorerContext?.connectionProfile; let convertedProfile: azdata.connection.ConnectionProfile = { providerId: profile.providerName, connectionId: profile.id, connectionName: profile.connectionName, serverName: profile.serverName, databaseName: profile.databaseName, userName: profile.userName, password: profile.password, authenticationType: profile.authenticationType, savePassword: profile.savePassword, groupFullName: profile.groupFullName, groupId: profile.groupId, saveProfile: profile.savePassword, azureTenantId: profile.azureTenantId, options: profile.options }; await doc.connect(convertedProfile); } } else { message = localizedConstants.NoActionScriptedMessage; } this.dialogObject.message = { text: message, level: azdata.window.MessageLevel.Information }; } catch (err) { this.dialogObject.message = { text: localizedConstants.scriptError(getErrorMessage(err)), level: azdata.window.MessageLevel.Error }; } finally { this.updateLoadingStatus(false, localizedConstants.GeneratingScriptText, localizedConstants.GeneratingScriptCompletedText); } } }