Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions frontend/src/components/Modals/ChatFeedback/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React, { useState } from "react";
import ModalWrapper from "@/components/ModalWrapper";
import { X } from "@phosphor-icons/react";
import Workspace from "@/models/workspace";
import { useTranslation } from "react-i18next";

export default function ChatFeedbackModal({
isOpen,
hideModal,
chatId,
slug,
onSubmitted,
}) {
const { t } = useTranslation();
const [comment, setComment] = useState("");
const [submitting, setSubmitting] = useState(false);

const handleSubmit = async (e) => {
e.preventDefault();
if (!chatId || !slug) {
hideModal();
return;
}
setSubmitting(true);
try {
// Only forward the comment to parent if there's content; feedback is optional
if (comment && comment.trim() !== "") {
onSubmitted && onSubmitted(comment.trim());
}
} catch (err) {
// ignore errors for now
}
setSubmitting(false);
hideModal();
};

return (
<ModalWrapper isOpen={isOpen}>
<div className="w-full max-w-lg bg-theme-bg-secondary rounded-lg shadow border-2 border-theme-modal-border overflow-hidden">
<div className="relative p-6 border-b rounded-t border-theme-modal-border">
<div className="w-full flex gap-x-2 items-center">
<h3 className="text-xl font-semibold text-white overflow-hidden overflow-ellipsis whitespace-nowrap">
{t("chat_window.provide_feedback")}
</h3>
</div>
<button
onClick={hideModal}
type="button"
className="absolute top-4 right-4 transition-all duration-300 bg-transparent rounded-lg text-sm p-1 inline-flex items-center hover:bg-theme-modal-border hover:border-theme-modal-border hover:border-opacity-50 border-transparent border"
>
<X size={24} weight="bold" className="text-white" />
</button>
</div>
<form onSubmit={handleSubmit}>
<div className="py-7 px-9 space-y-2">
<p className="text-sm text-theme-settings-input-placeholder">
{t("chat_window.bad_response_optional_feedback")}
</p>
<textarea
value={comment}
onChange={(e) => setComment(e.target.value)}
className="w-full min-h-[120px] p-3 rounded bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder outline-none"
placeholder={t("chat_window.bad_response_placeholder")}
/>
</div>
<div className="flex w-full justify-end items-center p-6 space-x-2 border-t border-theme-modal-border rounded-b">
<button
type="button"
onClick={hideModal}
className="transition-all duration-300 bg-transparent border border-theme-modal-border text-white hover:opacity-60 px-4 py-2 rounded-lg text-sm"
>
{t("chat_window.cancel")}
</button>
<button
type="submit"
disabled={submitting}
className="transition-all duration-300 bg-white text-black hover:opacity-60 px-4 py-2 rounded-lg text-sm"
>
{submitting ? t("common.saving") : t("common.save")}
</button>
</div>
</form>
</div>
</ModalWrapper>
);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import React, { memo, useState } from "react";
import useCopyText from "@/hooks/useCopyText";
import { Check, ThumbsUp, ArrowsClockwise, Copy } from "@phosphor-icons/react";
import {
Check,
ThumbsUp,
ThumbsDown,
ArrowsClockwise,
Copy,
} from "@phosphor-icons/react";
import Workspace from "@/models/workspace";
import ChatFeedbackModal from "@/components/Modals/ChatFeedback";
import { EditMessageAction } from "./EditMessage";
import RenderMetrics from "./RenderMetrics";
import ActionMenu from "./ActionMenu";
Expand All @@ -22,11 +29,19 @@ const Actions = ({
}) => {
const { t } = useTranslation();
const [selectedFeedback, setSelectedFeedback] = useState(feedbackScore);
const [showFeedbackModal, setShowFeedbackModal] = useState(false);
const [submittingComment, setSubmittingComment] = useState(false);
const handleFeedback = async (newFeedback) => {
const updatedFeedback =
selectedFeedback === newFeedback ? null : newFeedback;
// persist feedback score first
await Workspace.updateChatFeedback(chatId, slug, updatedFeedback);
setSelectedFeedback(updatedFeedback);

// If user just set negative feedback (not unsetting), show optional feedback modal
if (updatedFeedback === false) {
setShowFeedbackModal(true);
}
};

return (
Expand Down Expand Up @@ -55,6 +70,15 @@ const Actions = ({
IconComponent={ThumbsUp}
/>
)}
{chatId && role !== "user" && !isEditing && (
<FeedbackButton
isSelected={selectedFeedback === false}
handleFeedback={() => handleFeedback(false)}
tooltipId="feedback-button"
tooltipContent={t("chat_window.bad_response")}
IconComponent={ThumbsDown}
/>
)}
<ActionMenu
chatId={chatId}
forkThread={forkThread}
Expand All @@ -64,6 +88,20 @@ const Actions = ({
</div>
</div>
<RenderMetrics metrics={metrics} />
<ChatFeedbackModal
isOpen={showFeedbackModal}
hideModal={() => setShowFeedbackModal(false)}
chatId={chatId}
slug={slug}
onSubmitted={async (comment) => {
if (submittingComment) return;
setSubmittingComment(true);
try {
await Workspace.submitChatFeedbackComment(chatId, slug, comment);
} catch (e) {}
setSubmittingComment(false);
}}
/>
</div>
);
};
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/ar/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,10 @@ const TRANSLATIONS = {
regenerate: null,
regenerate_response: null,
good_response: null,
bad_response: null,
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: null,
hide_citations: null,
show_citations: null,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/da/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,10 @@ const TRANSLATIONS = {
regenerate: null,
regenerate_response: null,
good_response: null,
bad_response: null,
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: null,
hide_citations: null,
show_citations: null,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/de/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,10 @@ const TRANSLATIONS = {
regenerate: "Neu generieren",
regenerate_response: "Antwort neu generieren",
good_response: "Gute Antwort",
bad_response: "Schlechte Antwort",
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: "Weitere Aktionen",
hide_citations: "Quellenangaben ausblenden",
show_citations: "Quellenangaben anzeigen",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/en/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,10 @@ const TRANSLATIONS = {
regenerate: "Regenerate",
regenerate_response: "Regenerate response",
good_response: "Good response",
bad_response: "Bad response",
provide_feedback: "Provide Feedback",
bad_response_optional_feedback: "Optional feedback (help us improve)",
bad_response_placeholder: "Tell us what was wrong (optional)",
more_actions: "More actions",
hide_citations: "Hide citations",
show_citations: "Show citations",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/es/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,10 @@ const TRANSLATIONS = {
regenerate: "Regenerar",
regenerate_response: "Regenerar respuesta",
good_response: "Buena respuesta",
bad_response: "Mala respuesta",
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: "MΓ‘s acciones",
hide_citations: "Ocultar citas",
show_citations: "Mostrar citas",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/locales/et/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,7 @@ const TRANSLATIONS = {
regenerate: "Loo uuesti",
regenerate_response: "Loo vastus uuesti",
good_response: "Hea vastus",
bad_response: "Halb vastus",
more_actions: "Rohkem toiminguid",
hide_citations: "Peida viited",
show_citations: "NΓ€ita viiteid",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/fa/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,10 @@ const TRANSLATIONS = {
regenerate: null,
regenerate_response: null,
good_response: null,
bad_response: null,
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: null,
hide_citations: null,
show_citations: null,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/fr/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,10 @@ const TRANSLATIONS = {
regenerate: null,
regenerate_response: null,
good_response: null,
bad_response: null,
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: null,
hide_citations: null,
show_citations: null,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/he/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,10 @@ const TRANSLATIONS = {
regenerate: "Χ¦Χ•Χ¨ ΧžΧ—Χ“Χ©",
regenerate_response: "Χ¦Χ•Χ¨ ΧͺΧ’Χ•Χ‘Χ” ΧžΧ—Χ“Χ©",
good_response: "ΧͺΧ’Χ•Χ‘Χ” Χ˜Χ•Χ‘Χ”",
bad_response: "ΧͺΧ’Χ•Χ‘Χ” Χ¨Χ’Χ”",
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: "Χ€Χ’Χ•ΧœΧ•Χͺ Χ Χ•Χ‘Χ€Χ•Χͺ",
hide_citations: "Χ”Χ‘ΧͺΧ¨ Χ¦Χ™Χ˜Χ•Χ˜Χ™Χ",
show_citations: "Χ”Χ¦Χ’ Χ¦Χ™Χ˜Χ•Χ˜Χ™Χ",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/it/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,10 @@ const TRANSLATIONS = {
regenerate: null,
regenerate_response: null,
good_response: null,
bad_response: null,
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: null,
hide_citations: null,
show_citations: null,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/ja/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,10 @@ const TRANSLATIONS = {
regenerate: null,
regenerate_response: null,
good_response: null,
bad_response: null,
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: null,
hide_citations: null,
show_citations: null,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/ko/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,10 @@ const TRANSLATIONS = {
regenerate: "λ‹€μ‹œ 생성",
regenerate_response: "응닡 λ‹€μ‹œ 생성",
good_response: "쒋은 λ‹΅λ³€",
bad_response: "λ‚˜μœ λ‹΅λ³€",
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: "더 λ§Žμ€ μž‘μ—…",
hide_citations: "인용 숨기기",
show_citations: "인용 보기",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/lv/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,10 @@ const TRANSLATIONS = {
regenerate: null,
regenerate_response: null,
good_response: null,
bad_response: null,
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: null,
hide_citations: null,
show_citations: null,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/nl/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,10 @@ const TRANSLATIONS = {
regenerate: null,
regenerate_response: null,
good_response: null,
bad_response: null,
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: null,
hide_citations: null,
show_citations: null,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/pl/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ const TRANSLATIONS = {
selection: "WybΓ³r modelu",
saving: "Zapisywanie...",
save: "Zapisz zmiany",
bad_response: "ZΕ‚a odpowiedΕΊ",
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
previous: "Poprzednia strona",
next: "NastΔ™pna strona",
optional: "Opcjonalnie",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/pt_BR/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,10 @@ const TRANSLATIONS = {
regenerate: "Regerar",
regenerate_response: "Regerar resposta",
good_response: "Resposta satisfatΓ³ria",
bad_response: "Resposta ruim",
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: "Mais aΓ§Γ΅es",
hide_citations: "Esconder citaΓ§Γ΅es",
show_citations: "Exibir citaΓ§Γ΅es",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/ru/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,10 @@ const TRANSLATIONS = {
regenerate: null,
regenerate_response: null,
good_response: null,
bad_response: null,
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: null,
hide_citations: null,
show_citations: null,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/vn/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,10 @@ const TRANSLATIONS = {
regenerate: null,
regenerate_response: null,
good_response: null,
bad_response: null,
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: null,
hide_citations: null,
show_citations: null,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/zh/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,10 @@ const TRANSLATIONS = {
regenerate: "重新",
regenerate_response: "ι‡ζ–°ε›žεΊ”",
good_response: "反应良ε₯½",
bad_response: "δΈθ‰―ε›žε€",
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: "ζ›΄ε€šζ“δ½œ",
hide_citations: "ιšθ—εΌ•ζ–‡",
show_citations: "ζ˜Ύη€ΊεΌ•ζ–‡",
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/locales/zh_TW/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,10 @@ const TRANSLATIONS = {
regenerate: "重新",
regenerate_response: "ι‡ζ–°ε›žζ‡‰",
good_response: "反應良ε₯½",
bad_response: "δΈθ‰―ε›žζ‡‰",
provide_feedback: null,
bad_response_optional_feedback: null,
bad_response_placeholder: null,
more_actions: "ζ›΄ε€šζ“δ½œ",
hide_citations: "ιš±θ—εΌ•ζ–‡",
show_citations: "ι‘―η€ΊεΌ•ζ–‡",
Expand Down
14 changes: 14 additions & 0 deletions frontend/src/models/workspace.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,20 @@ const Workspace = {
.catch(() => false);
return result;
},
submitChatFeedbackComment: async function (chatId, slug, comment) {
if (!chatId || !slug || !comment) return false;
const result = await fetch(
`${API_BASE}/workspace/${slug}/chat-feedback/${chatId}/comment`,
{
method: "POST",
headers: baseHeaders(),
body: JSON.stringify({ comment }),
}
)
.then((res) => res.ok)
.catch(() => false);
return result;
},

deleteChats: async function (slug = "", chatIds = []) {
return await fetch(`${API_BASE}/workspace/${slug}/delete-chats`, {
Expand Down
Loading