adding feedback dialog and support request buttons

This commit is contained in:
Brian Harris
2021-05-20 14:09:45 -07:00
parent 8a0c183114
commit 866ced5c08
13 changed files with 306 additions and 8 deletions

View 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;
}
}
}

View File

@@ -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'