Skip to content

Commit

Permalink
Update feedback dialog form
Browse files Browse the repository at this point in the history
  • Loading branch information
ajbozarth committed Nov 1, 2024
1 parent 7b0202b commit 021b361
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 34 deletions.
144 changes: 110 additions & 34 deletions src/service/feedback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,25 @@

import React from 'react';

import { InputDialog, Notification } from '@jupyterlab/apputils';
import { Dialog, Notification } from '@jupyterlab/apputils';
import { ReactWidget } from '@jupyterlab/ui-components';

import { postFeedback } from './api';
import { getCurrentModel } from './modelHandler';
import { lastPrompt } from '../QiskitCompletionProvider';
import { feedbackIcon } from '../utils/icons';
import { IFeedbackResponse } from '../utils/schema';
import { IFeedbackForm, IFeedbackResponse } from '../utils/schema';

const DIALOG_TITLE = 'Qiskit Code Assistant Feedback';
const toBool = (bool?: string): boolean | undefined => {
switch (bool) {
case 'true':
return true;
case 'false':
return false;
default:
return undefined;
}
};

export function getFeedbackStatusBarWidget() {
const feedbackButton = ReactWidget.create(
Expand All @@ -49,39 +58,106 @@ export function getFeedbackStatusBarWidget() {
}

export function getFeedback(prompt: boolean = true) {
return InputDialog.getText({
title: DIALOG_TITLE,
label: prompt ? lastPrompt?.items[0] : undefined
}).then(result => {
// send feedback
if (result.button.accept) {
sendFeedback(
getCurrentModel()?._id,
prompt ? lastPrompt?.prompt_id : undefined,
undefined,
result.value || undefined
);
}
const model_id = getCurrentModel()?._id;
const prompt_id = prompt ? lastPrompt?.prompt_id : undefined;
const prompt_text = prompt ? lastPrompt?.items[0] : undefined;

const dialog = new Dialog({
title: 'Qiskit Code Assistant Feedback',
body: getFeedbackBodyWidget(prompt_text),
buttons: [Dialog.cancelButton(), Dialog.okButton({ label: 'Submit' })],
focusNodeSelector: '.jp-qiskit-code-assistant-feedback-form textarea'
});
}

function sendFeedback(
model_id?: string,
prompt_id?: string,
positive_feedback?: boolean,
comment?: string
) {
console.log(
`model_id: ${model_id}`,
`prompt_id: ${prompt_id}`,
`positive_feedback: ${positive_feedback}`,
`comment: ${comment}`
);
postFeedback(model_id, prompt_id, positive_feedback, comment).then(
(response: IFeedbackResponse) => {
Notification.info(`Qiskit Code Assistant:\n${response['message']}`, {
autoClose: false
const dialogHandleEvent = dialog.handleEvent;
dialog.handleEvent = (event: Event) => {
if (
event.type === 'keydown' &&
(event as KeyboardEvent).code === 'Enter' &&
document.activeElement instanceof HTMLTextAreaElement
) {
return;
}
dialogHandleEvent.call(dialog, event);
};

return dialog.launch().then(result => {
if (
result.button.accept &&
(result.value?.positive_feedback || result.value?.comment)
) {
postFeedback(
model_id,
prompt_id,
toBool(result.value?.positive_feedback),
result.value?.comment
).then((response: IFeedbackResponse) => {
Notification.info(`Qiskit Code Assistant:\n${response['message']}`, {
autoClose: 5000
});
});
}
);
});
}

function getFeedbackBodyWidget(
prompt?: string
): Dialog.IBodyWidget<IFeedbackForm> {
const bodyWidget = ReactWidget.create(
<>
{!!prompt && (
<>
<b>Completion</b>
<pre>{prompt.trim()}</pre>
</>
)}
<form>
{!!prompt && (
<p>
How helpful was this completion? &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<label>
<input type="radio" name="positive_feedback" value="true" />
<span className="positive-feedback">&#128077;</span>
</label>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<label>
<input type="radio" name="positive_feedback" value="false" />
<span className="positive-feedback">&#128078;</span>
</label>
</p>
)}
<p>
<label>
<p>
{prompt
? 'Additional feedback (Optional)'
: 'Please share your experience with Qiskit Code Assistant'}
</p>
<textarea name="comment"></textarea>
</label>
</p>
</form>
</>
) as Dialog.IBodyWidget<IFeedbackForm>;

bodyWidget.addClass('jp-qiskit-code-assistant-feedback-form');
if (prompt) {
bodyWidget.addClass('jp-qiskit-code-assistant-feedback-prompt');
} else {
bodyWidget.addClass('jp-qiskit-code-assistant-feedback-general');
}

bodyWidget.getValue = (): IFeedbackForm => {
const form = bodyWidget.node.querySelector('form');
const formData = new FormData(form ? form : undefined);
const positive_feedback = formData.get('positive_feedback') as string;
const comment = formData.get('comment') as string;

return {
positive_feedback: positive_feedback ? positive_feedback : undefined,
comment: comment ? comment : undefined
};
};

return bodyWidget;
}
5 changes: 5 additions & 0 deletions src/utils/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,8 @@ export interface ICompletionReturn {
items: string[];
prompt_id: string;
}

export interface IFeedbackForm {
positive_feedback?: string;
comment?: string;
}
17 changes: 17 additions & 0 deletions style/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@
cursor: pointer;
}

.positive-feedback {
font-size: large;
}
.jp-qiskit-code-assistant-feedback-prompt pre {
overflow: auto;
max-height: 200px;
border: solid thin;
}

.jp-qiskit-code-assistant-feedback-prompt textarea,
.jp-qiskit-code-assistant-feedback-general textarea {
width: 30em;
height: 5em;
font-family: inherit;
font-size: inherit;
}

.jp-qiskit-code-assistant-statusbar {
margin: 4px;
cursor: pointer;
Expand Down

0 comments on commit 021b361

Please sign in to comment.