mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-11-09 07:23:14 +00:00
Include optional feedback sentiment and direct support contact
This commit is contained in:
1 parent
ee4876bd18
commit
cdab2fbdd0
13 files changed
+118
-14
No files matched your search
@@ -215,7 +215,9 @@ export function FeedbackDialog({
|
||||
aria-label={t(`common.feedback.${item.value}`, item.label)}
|
||||
aria-pressed={sentiment === item.value}
|
||||
isDisabled={sending}
|
||||
onPress={() => setSentiment(item.value)}
|
||||
onPress={() =>
|
||||
setSentiment(sentiment === item.value ? null : item.value)
|
||||
}
|
||||
>
|
||||
<span aria-hidden="true">{item.emoji}</span>
|
||||
</Button>
|
||||
@@ -305,7 +307,7 @@ export function FeedbackDialog({
|
||||
<Description className="text-xs">
|
||||
{t(
|
||||
"common.feedback.diagnostics",
|
||||
"Relevant diagnostic logs will be attached.",
|
||||
"Diagnostic logs attached. Feedback sent to support@recordly.dev",
|
||||
)}
|
||||
</Description>
|
||||
{error && (
|
||||
@@ -320,6 +322,24 @@ export function FeedbackDialog({
|
||||
</Button>
|
||||
</Form>
|
||||
)}
|
||||
{!sent && (
|
||||
<p className="text-center text-xs text-muted">
|
||||
{t("common.feedback.orEmail", "Or email")}{" "}
|
||||
<a
|
||||
href="mailto:support@recordly.dev"
|
||||
className="underline underline-offset-4"
|
||||
onClick={(event) => {
|
||||
if (!window.electronAPI?.openExternalUrl) return;
|
||||
event.preventDefault();
|
||||
void window.electronAPI.openExternalUrl(
|
||||
"mailto:support@recordly.dev",
|
||||
);
|
||||
}}
|
||||
>
|
||||
support@recordly.dev
|
||||
</a>
|
||||
</p>
|
||||
)}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -36,13 +36,14 @@
|
||||
"thanks": "Danke für dein Feedback",
|
||||
"signInRequired": "Melde dich an, um Feedback zu senden.",
|
||||
"openHome": "Öffne die Startseite, um dich anzumelden.",
|
||||
"orEmail": "Oder per E-Mail an",
|
||||
"subject": "Betreff",
|
||||
"subjectPlaceholder": "Was möchtest du uns mitteilen?",
|
||||
"description": "Beschreibung",
|
||||
"descriptionPlaceholder": "Wir lesen jedes Feedback...",
|
||||
"attachFiles": "Dateien anhängen",
|
||||
"removeFile": "{{name}} entfernen",
|
||||
"diagnostics": "Relevante Diagnoseprotokolle werden angehängt.",
|
||||
"diagnostics": "Diagnoseprotokolle angehängt. Feedback an support@recordly.dev gesendet",
|
||||
"sending": "Wird gesendet…",
|
||||
"errors": {
|
||||
"unavailable": "Feedback ist erst verfügbar, wenn die Kontodienste eingerichtet sind.",
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"thanks": "Thanks for your feedback",
|
||||
"signInRequired": "Sign in to send feedback.",
|
||||
"openHome": "Open Home to sign in.",
|
||||
"orEmail": "Or email",
|
||||
"missingMessage": "Tell us more before sending.",
|
||||
"sentiment": "How do you feel?",
|
||||
"loving": "Loving",
|
||||
@@ -47,7 +48,7 @@
|
||||
"descriptionPlaceholder": "We read all feedback...",
|
||||
"attachFiles": "Attach files",
|
||||
"removeFile": "Remove {{name}}",
|
||||
"diagnostics": "Relevant diagnostic logs will be attached.",
|
||||
"diagnostics": "Diagnostic logs attached. Feedback sent to support@recordly.dev",
|
||||
"sending": "Sending…",
|
||||
"errors": {
|
||||
"unavailable": "Feedback is unavailable until account services are configured.",
|
||||
|
||||
@@ -36,13 +36,14 @@
|
||||
"thanks": "Gracias por tus comentarios",
|
||||
"signInRequired": "Inicia sesión para enviar comentarios.",
|
||||
"openHome": "Abre Inicio para iniciar sesión.",
|
||||
"orEmail": "O escribe a",
|
||||
"subject": "Asunto",
|
||||
"subjectPlaceholder": "¿Qué tienes en mente?",
|
||||
"description": "Descripción",
|
||||
"descriptionPlaceholder": "Leemos todos los comentarios...",
|
||||
"attachFiles": "Adjuntar archivos",
|
||||
"removeFile": "Eliminar {{name}}",
|
||||
"diagnostics": "Se adjuntarán los registros de diagnóstico pertinentes.",
|
||||
"diagnostics": "Registros de diagnóstico adjuntos. Comentarios enviados a support@recordly.dev",
|
||||
"sending": "Enviando…",
|
||||
"errors": {
|
||||
"unavailable": "Los comentarios no están disponibles hasta que se configuren los servicios de cuenta.",
|
||||
|
||||
@@ -36,13 +36,14 @@
|
||||
"thanks": "Merci pour vos commentaires",
|
||||
"signInRequired": "Connectez-vous pour envoyer des commentaires.",
|
||||
"openHome": "Ouvrez l’accueil pour vous connecter.",
|
||||
"orEmail": "Ou écrivez à",
|
||||
"subject": "Objet",
|
||||
"subjectPlaceholder": "Que souhaitez-vous nous dire ?",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Nous lisons tous les commentaires...",
|
||||
"attachFiles": "Joindre des fichiers",
|
||||
"removeFile": "Retirer {{name}}",
|
||||
"diagnostics": "Les journaux de diagnostic pertinents seront joints.",
|
||||
"diagnostics": "Journaux de diagnostic joints. Commentaires envoyés à support@recordly.dev",
|
||||
"sending": "Envoi…",
|
||||
"errors": {
|
||||
"unavailable": "Les commentaires seront disponibles une fois les services de compte configurés.",
|
||||
|
||||
@@ -36,13 +36,14 @@
|
||||
"thanks": "Grazie per i tuoi commenti",
|
||||
"signInRequired": "Accedi per inviare commenti.",
|
||||
"openHome": "Apri Home per accedere.",
|
||||
"orEmail": "Oppure scrivi a",
|
||||
"subject": "Oggetto",
|
||||
"subjectPlaceholder": "Cosa vorresti dirci?",
|
||||
"description": "Descrizione",
|
||||
"descriptionPlaceholder": "Leggiamo tutti i commenti...",
|
||||
"attachFiles": "Allega file",
|
||||
"removeFile": "Rimuovi {{name}}",
|
||||
"diagnostics": "Verranno allegati i registri diagnostici pertinenti.",
|
||||
"diagnostics": "Registri diagnostici allegati. Feedback inviato a support@recordly.dev",
|
||||
"sending": "Invio…",
|
||||
"errors": {
|
||||
"unavailable": "I commenti saranno disponibili dopo la configurazione dei servizi dell’account.",
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"thanks": "フィードバックありがとうございます",
|
||||
"signInRequired": "フィードバックを送信するにはログインしてください。",
|
||||
"openHome": "ホームを開いてログインしてください。",
|
||||
"orEmail": "またはメール",
|
||||
"missingMessage": "送信する前に内容を入力してください。",
|
||||
"sentiment": "使い心地はいかがですか?",
|
||||
"loving": "満足",
|
||||
@@ -47,7 +48,7 @@
|
||||
"descriptionPlaceholder": "すべてのフィードバックに目を通しています…",
|
||||
"attachFiles": "ファイルを添付",
|
||||
"removeFile": "{{name}}を削除",
|
||||
"diagnostics": "関連する診断ログが添付されます。",
|
||||
"diagnostics": "診断ログを添付。フィードバックは support@recordly.dev に送信されます",
|
||||
"sending": "送信中…",
|
||||
"errors": {
|
||||
"unavailable": "アカウントサービスが設定されるまで、フィードバックは利用できません。",
|
||||
|
||||
@@ -36,13 +36,14 @@
|
||||
"thanks": "피드백을 보내 주셔서 감사합니다",
|
||||
"signInRequired": "피드백을 보내려면 로그인하세요.",
|
||||
"openHome": "홈을 열어 로그인하세요.",
|
||||
"orEmail": "또는 이메일",
|
||||
"subject": "제목",
|
||||
"subjectPlaceholder": "어떤 의견이 있으신가요?",
|
||||
"description": "설명",
|
||||
"descriptionPlaceholder": "모든 피드백을 읽고 있습니다...",
|
||||
"attachFiles": "파일 첨부",
|
||||
"removeFile": "{{name}} 제거",
|
||||
"diagnostics": "관련 진단 로그가 첨부됩니다.",
|
||||
"diagnostics": "진단 로그가 첨부되었습니다. 피드백이 support@recordly.dev로 전송됩니다",
|
||||
"sending": "전송 중…",
|
||||
"errors": {
|
||||
"unavailable": "계정 서비스가 구성되어야 피드백을 보낼 수 있습니다.",
|
||||
|
||||
@@ -36,13 +36,14 @@
|
||||
"thanks": "Bedankt voor je feedback",
|
||||
"signInRequired": "Meld je aan om feedback te verzenden.",
|
||||
"openHome": "Open Start om je aan te melden.",
|
||||
"orEmail": "Of mail naar",
|
||||
"subject": "Onderwerp",
|
||||
"subjectPlaceholder": "Wat wil je ons vertellen?",
|
||||
"description": "Beschrijving",
|
||||
"descriptionPlaceholder": "We lezen alle feedback...",
|
||||
"attachFiles": "Bestanden bijvoegen",
|
||||
"removeFile": "{{name}} verwijderen",
|
||||
"diagnostics": "Relevante diagnostische logboeken worden bijgevoegd.",
|
||||
"diagnostics": "Diagnostische logboeken bijgevoegd. Feedback verzonden naar support@recordly.dev",
|
||||
"sending": "Verzenden…",
|
||||
"errors": {
|
||||
"unavailable": "Feedback is pas beschikbaar nadat de accountdiensten zijn ingesteld.",
|
||||
|
||||
@@ -36,13 +36,14 @@
|
||||
"thanks": "Obrigado pelos comentários",
|
||||
"signInRequired": "Entre para enviar comentários.",
|
||||
"openHome": "Abra a página inicial para entrar.",
|
||||
"orEmail": "Ou envie um e-mail para",
|
||||
"subject": "Assunto",
|
||||
"subjectPlaceholder": "O que você gostaria de compartilhar?",
|
||||
"description": "Descrição",
|
||||
"descriptionPlaceholder": "Lemos todos os comentários...",
|
||||
"attachFiles": "Anexar arquivos",
|
||||
"removeFile": "Remover {{name}}",
|
||||
"diagnostics": "Os registros de diagnóstico relevantes serão anexados.",
|
||||
"diagnostics": "Registros de diagnóstico anexados. Comentários enviados para support@recordly.dev",
|
||||
"sending": "Enviando…",
|
||||
"errors": {
|
||||
"unavailable": "O envio de comentários ficará disponível após a configuração dos serviços da conta.",
|
||||
|
||||
@@ -36,13 +36,14 @@
|
||||
"thanks": "感谢你的反馈",
|
||||
"signInRequired": "登录以发送反馈。",
|
||||
"openHome": "打开首页以登录。",
|
||||
"orEmail": "或发送邮件至",
|
||||
"subject": "主题",
|
||||
"subjectPlaceholder": "你有什么想法?",
|
||||
"description": "说明",
|
||||
"descriptionPlaceholder": "我们会阅读所有反馈...",
|
||||
"attachFiles": "添加附件",
|
||||
"removeFile": "移除 {{name}}",
|
||||
"diagnostics": "将附上相关诊断日志。",
|
||||
"diagnostics": "已附上诊断日志。反馈发送至 support@recordly.dev",
|
||||
"sending": "正在发送…",
|
||||
"errors": {
|
||||
"unavailable": "配置账户服务后才能使用反馈功能。",
|
||||
|
||||
@@ -36,13 +36,14 @@
|
||||
"thanks": "感謝你的意見回饋",
|
||||
"signInRequired": "登入以傳送意見回饋。",
|
||||
"openHome": "開啟首頁以登入。",
|
||||
"orEmail": "或寄送郵件至",
|
||||
"subject": "主旨",
|
||||
"subjectPlaceholder": "你有什麼想法?",
|
||||
"description": "說明",
|
||||
"descriptionPlaceholder": "我們會閱讀所有意見回饋...",
|
||||
"attachFiles": "附加檔案",
|
||||
"removeFile": "移除 {{name}}",
|
||||
"diagnostics": "將附上相關診斷記錄。",
|
||||
"diagnostics": "已附上診斷記錄。意見回饋傳送至 support@recordly.dev",
|
||||
"sending": "正在傳送…",
|
||||
"errors": {
|
||||
"unavailable": "設定帳號服務後才能使用意見回饋功能。",
|
||||
|
||||
@@ -1,6 +1,79 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { installDesktopBridge } from "./bridge";
|
||||
|
||||
for (const clearSelection of [false, true]) {
|
||||
test(`feedback submits without an emoji${clearSelection ? " after clearing a selection" : ""}`, async ({
|
||||
page,
|
||||
}) => {
|
||||
await installDesktopBridge(page);
|
||||
let requestBody = "";
|
||||
await page.route("**/functions/v1/submit-feedback", async (route) => {
|
||||
requestBody = route.request().postData() ?? "";
|
||||
await route.fulfill({ json: { success: true } });
|
||||
});
|
||||
await page.goto("/?windowType=editor");
|
||||
await page.getByRole("button", { name: "Recordly account", exact: true }).click();
|
||||
await page
|
||||
.getByRole("dialog", { name: "Account menu", exact: true })
|
||||
.getByRole("button", { name: "Feedback", exact: true })
|
||||
.click();
|
||||
const modal = page.getByRole("dialog", { name: "Send feedback", exact: true });
|
||||
if (clearSelection) {
|
||||
const loving = modal.getByRole("button", { name: "Loving", exact: true });
|
||||
await loving.click();
|
||||
await expect(loving).toHaveAttribute("aria-pressed", "true");
|
||||
await loving.click();
|
||||
}
|
||||
await expect(modal.locator('[aria-pressed="true"]')).toHaveCount(0);
|
||||
await modal.getByRole("button", { name: "Send feedback", exact: true }).click();
|
||||
await expect(modal).toBeVisible();
|
||||
expect(requestBody).toBe("");
|
||||
await modal
|
||||
.getByLabel("Description", { exact: true })
|
||||
.fill("Please add more keyboard shortcuts.");
|
||||
await modal.getByRole("button", { name: "Send feedback", exact: true }).click();
|
||||
await expect(
|
||||
page.getByRole("dialog", { name: "Thanks for your feedback", exact: true }),
|
||||
).toBeVisible();
|
||||
expect(requestBody).toContain('name="title"\r\n\r\nPlease add more keyboard shortcuts.');
|
||||
expect(requestBody).not.toMatch(/🥰|😐|😠/u);
|
||||
});
|
||||
}
|
||||
|
||||
for (const signedIn of [false, true]) {
|
||||
test(`feedback offers support email when signed ${signedIn ? "in" : "out"}`, async ({
|
||||
page,
|
||||
}) => {
|
||||
await installDesktopBridge(page, undefined, { signedIn });
|
||||
await page.addInitScript(() => {
|
||||
window.electronAPI.openExternalUrl = async (url: string) => {
|
||||
document.documentElement.dataset.openedExternalUrl = url;
|
||||
return { success: true };
|
||||
};
|
||||
});
|
||||
await page.goto("/?windowType=editor");
|
||||
if (signedIn) {
|
||||
await page.getByRole("button", { name: "Recordly account", exact: true }).click();
|
||||
await page
|
||||
.getByRole("dialog", { name: "Account menu", exact: true })
|
||||
.getByRole("button", { name: "Feedback", exact: true })
|
||||
.click();
|
||||
} else {
|
||||
await page.getByRole("button", { name: "Feedback", exact: true }).click();
|
||||
}
|
||||
const modal = page.getByRole("dialog", { name: "Send feedback", exact: true });
|
||||
await expect(modal.getByText("Or email", { exact: false })).toBeVisible();
|
||||
const email = modal.getByRole("link", { name: "support@recordly.dev", exact: true });
|
||||
await expect(email).toHaveAttribute("href", "mailto:support@recordly.dev");
|
||||
await email.click();
|
||||
await expect(page.locator("html")).toHaveAttribute(
|
||||
"data-opened-external-url",
|
||||
"mailto:support@recordly.dev",
|
||||
);
|
||||
await expect(modal).toBeVisible();
|
||||
});
|
||||
}
|
||||
|
||||
test("feedback preserves a draft on failure, supports attachments, and includes diagnostics automatically", async ({
|
||||
page,
|
||||
}) => {
|
||||
@@ -31,7 +104,7 @@ test("feedback preserves a draft on failure, supports attachments, and includes
|
||||
await expect(modal.getByText("notes.txt", { exact: true })).toBeVisible();
|
||||
await modal.getByRole("button", { name: "Remove notes.txt" }).click();
|
||||
await expect(modal.getByText("notes.txt", { exact: true })).toHaveCount(0);
|
||||
await expect(modal.getByText("Relevant diagnostic logs will be attached.")).toBeVisible();
|
||||
await expect(modal.getByText("Diagnostic logs attached. Feedback sent to support@recordly.dev")).toBeVisible();
|
||||
await expect(modal.getByRole("checkbox")).toHaveCount(0);
|
||||
await expect(modal.getByLabel("Title", { exact: true })).toHaveCount(0);
|
||||
await modal.getByRole("button", { name: "Send feedback", exact: true }).click();
|
||||
|
||||
Reference in new issue
Block a user