mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-26 17:23:15 -05:00
adding feedback dialog and support request buttons
This commit is contained in:
184
extensions/sql-migration/src/dialog/feedbackDialog.ts
Normal file
184
extensions/sql-migration/src/dialog/feedbackDialog.ts
Normal file
@@ -0,0 +1,184 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { IconPathHelper } from '../constants/iconPathHelper';
|
||||
import * as loc from '../constants/strings';
|
||||
import { sendSqlMigrationActionEvent, TelemetryActions, TelemetryViews } from '../telemtery';
|
||||
|
||||
export class FeedbackDialog {
|
||||
|
||||
private static readonly DialogName: string = 'FeedbackDialog';
|
||||
|
||||
private _dialog!: azdata.window.Dialog;
|
||||
private _buttonGroup!: azdata.FlexContainer;
|
||||
private _isOpen: boolean = false;
|
||||
private _feedbackRating?: number;
|
||||
private _feedbackText?: string;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
public async openDialog() {
|
||||
if (!this._isOpen) {
|
||||
this._isOpen = true;
|
||||
this._dialog = azdata.window.createModelViewDialog(
|
||||
'',
|
||||
FeedbackDialog.DialogName,
|
||||
360,
|
||||
'normal',
|
||||
'below');
|
||||
|
||||
this._dialog.registerContent(async view => {
|
||||
const headingGroup = view.modelBuilder
|
||||
.flexContainer()
|
||||
.withItems([
|
||||
view.modelBuilder
|
||||
.image()
|
||||
.withProperties<azdata.ImageComponentProperties>({
|
||||
iconPath: IconPathHelper.sendFeedback,
|
||||
iconHeight: 32,
|
||||
iconWidth: 32,
|
||||
height: 32,
|
||||
width: 32,
|
||||
})
|
||||
.component(),
|
||||
view.modelBuilder
|
||||
.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.FEEDBACK_DIALOG_HEADING,
|
||||
CSSStyles: {
|
||||
'margin': '0 0 0 10px',
|
||||
},
|
||||
})
|
||||
.component(),
|
||||
])
|
||||
.withLayout({
|
||||
width: '100%',
|
||||
alignContent: 'flex-start',
|
||||
flexFlow: 'row',
|
||||
})
|
||||
.component();
|
||||
|
||||
this._buttonGroup = view.modelBuilder
|
||||
.flexContainer()
|
||||
.withItems([
|
||||
this._createFeedbackButton(view, 0, loc.FEEDBACK_DIALOG_RATING_1),
|
||||
this._createFeedbackButton(view, 1, loc.FEEDBACK_DIALOG_RATING_2),
|
||||
this._createFeedbackButton(view, 2, loc.FEEDBACK_DIALOG_RATING_3),
|
||||
this._createFeedbackButton(view, 3, loc.FEEDBACK_DIALOG_RATING_4),
|
||||
this._createFeedbackButton(view, 4, loc.FEEDBACK_DIALOG_RATING_5),
|
||||
])
|
||||
.withLayout({
|
||||
alignContent: 'flex-start',
|
||||
flexFlow: 'row',
|
||||
})
|
||||
.withProperties<azdata.ComponentProperties>({
|
||||
display: 'inline-flex',
|
||||
ariaLabel: loc.FEEDBACK_DIALOG_HEADING,
|
||||
})
|
||||
.component();
|
||||
|
||||
const feedbackInputBox = view.modelBuilder
|
||||
.inputBox()
|
||||
.withProperties<azdata.InputBoxProperties>({
|
||||
rows: 3,
|
||||
inputType: 'text',
|
||||
multiline: true,
|
||||
placeHolder: loc.FEEDBACK_DIALOG_PLACEHOLDER,
|
||||
CSSStyles: {
|
||||
'white-space': 'normal!important',
|
||||
},
|
||||
})
|
||||
.component();
|
||||
|
||||
feedbackInputBox.onTextChanged(
|
||||
value => this._feedbackText = value);
|
||||
|
||||
const formModel = view.modelBuilder
|
||||
.formContainer()
|
||||
.withFormItems([{
|
||||
components: [
|
||||
{
|
||||
component: headingGroup,
|
||||
},
|
||||
{
|
||||
component: this._buttonGroup,
|
||||
},
|
||||
{
|
||||
component: feedbackInputBox,
|
||||
}
|
||||
],
|
||||
title: ''
|
||||
}])
|
||||
.withLayout({ width: '100%' })
|
||||
.component();
|
||||
|
||||
await view.initializeModel(formModel);
|
||||
await this._buttonGroup.items[0].focus();
|
||||
});
|
||||
|
||||
this._dialog.okButton.label = loc.FEEDBACK_DIALOG_SUBMIT_BUTTON;
|
||||
this._dialog.okButton.onClick(async () => await this._execute());
|
||||
|
||||
this._dialog.cancelButton.label = loc.FEEDBACK_DIALOG_CANCEL_BUTTON;
|
||||
this._dialog.cancelButton.onClick(() => this._cancel());
|
||||
|
||||
azdata.window.openDialog(this._dialog);
|
||||
}
|
||||
}
|
||||
|
||||
private async _execute() {
|
||||
sendSqlMigrationActionEvent(
|
||||
TelemetryViews.FeedbackDialog,
|
||||
TelemetryActions.SendFeedback,
|
||||
{
|
||||
'FeedbackRating': this._feedbackRating?.toString() || '',
|
||||
'FeedbackMessage': this._feedbackText?.substr(0, 500) || '',
|
||||
});
|
||||
|
||||
await vscode.window.showInformationMessage(loc.FEEDBACK_DIALOG_SENT_MESSAGE);
|
||||
this._isOpen = false;
|
||||
}
|
||||
|
||||
private _cancel() {
|
||||
this._isOpen = false;
|
||||
}
|
||||
|
||||
private _createFeedbackButton(view: azdata.ModelView, index: number, ariaLabel: string): azdata.Component {
|
||||
const button = view.modelBuilder
|
||||
.button()
|
||||
.withProperties<azdata.ButtonProperties>({
|
||||
ariaLabel: ariaLabel,
|
||||
height: '26px',
|
||||
width: '26px',
|
||||
buttonType: azdata.ButtonType.Normal,
|
||||
iconHeight: '24px',
|
||||
iconWidth: '24px',
|
||||
iconPath: IconPathHelper.blueStar,
|
||||
CSSStyles: {
|
||||
'margin': '0 10px 0 0',
|
||||
'padding': '0 0 0 0',
|
||||
},
|
||||
})
|
||||
.component();
|
||||
|
||||
button.onDidClick(() => this._updateButtonImages(index));
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
private _updateButtonImages(index: number): void {
|
||||
const items: azdata.Component[] = this._buttonGroup?.items || [];
|
||||
this._feedbackRating = index;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const btn = items[i] as azdata.ButtonComponent;
|
||||
btn.iconPath = i <= index
|
||||
? IconPathHelper.solidBlueStar
|
||||
: IconPathHelper.blueStar;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ export class MigrationCutoverDialog {
|
||||
private _cancelButton!: azdata.ButtonComponent;
|
||||
private _refreshLoader!: azdata.LoadingComponent;
|
||||
private _copyDatabaseMigrationDetails!: azdata.ButtonComponent;
|
||||
private _newSupportRequest!: azdata.ButtonComponent;
|
||||
|
||||
private _serverName!: azdata.TextComponent;
|
||||
private _serverVersion!: azdata.TextComponent;
|
||||
@@ -371,7 +372,6 @@ export class MigrationCutoverDialog {
|
||||
flex: '0'
|
||||
});
|
||||
|
||||
|
||||
this._refreshButton = this._view.modelBuilder.button().withProps({
|
||||
iconPath: IconPathHelper.refresh,
|
||||
iconHeight: '16px',
|
||||
@@ -419,6 +419,30 @@ export class MigrationCutoverDialog {
|
||||
}
|
||||
});
|
||||
|
||||
// create new support request button. Hiding button until sql migration support has been setup.
|
||||
this._newSupportRequest = this._view.modelBuilder.button().withProps({
|
||||
label: loc.NEW_SUPPORT_REQUEST,
|
||||
iconPath: IconPathHelper.newSupportRequest,
|
||||
iconHeight: '16px',
|
||||
iconWidth: '16px',
|
||||
height: '20px',
|
||||
width: '140px',
|
||||
display: 'none' // remove when support requests are setup for sql migrations
|
||||
}).component();
|
||||
|
||||
this._newSupportRequest.onDidClick(async (e) => {
|
||||
const serviceId = this._model._migration.controller.id;
|
||||
const supportUrl = `https://portal.azure.com/#resource${serviceId}/supportrequest`;
|
||||
await vscode.env.openExternal(vscode.Uri.parse(supportUrl));
|
||||
});
|
||||
|
||||
headerActions.addItem(this._newSupportRequest, {
|
||||
flex: '0',
|
||||
CSSStyles: {
|
||||
'margin-left': '5px'
|
||||
}
|
||||
});
|
||||
|
||||
this._refreshLoader = this._view.modelBuilder.loadingComponent().withProps({
|
||||
loading: false,
|
||||
height: '15px'
|
||||
|
||||
Reference in New Issue
Block a user