mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 02:10:12 -06:00
fixes coderabbit feedback
This commit is contained in:
@@ -3603,7 +3603,7 @@ export const customSurveyTemplate = (t: TFunction): TTemplate => {
|
||||
blocks: [
|
||||
{
|
||||
id: createId(),
|
||||
name: "Block 1",
|
||||
name: t("templates.custom_survey_block_1_name"),
|
||||
elements: [
|
||||
{
|
||||
id: createId(),
|
||||
|
||||
@@ -1352,7 +1352,6 @@ checksums:
|
||||
environments/surveys/edit/is_skipped: 9fb90b6578f603cca37d4e6c912bb401
|
||||
environments/surveys/edit/is_submitted: 13e774a97ad5f5609555e6f99514e70f
|
||||
environments/surveys/edit/italic: 555c60fb1d12ae305136202afa6deb3d
|
||||
environments/surveys/edit/jump_to_block: 2fc00bd725c44f98861051c57bb2c392
|
||||
environments/surveys/edit/jump_to_question: 742aabed8845190825418aa429f01b2d
|
||||
environments/surveys/edit/keep_current_order: a7c944ad6b3515f2c4f83a2c81f8fc26
|
||||
environments/surveys/edit/keep_showing_while_conditions_match: 2574802d87bd6da151c9145aacce7281
|
||||
|
||||
@@ -2248,6 +2248,7 @@
|
||||
"csat_survey_question_3_headline": "Ugh, sorry! Können wir irgendwas tun, um deine Erfahrung zu verbessern?",
|
||||
"csat_survey_question_3_placeholder": "Tippe deine Antwort hier...",
|
||||
"cta_description": "Information anzeigen und Benutzer auffordern, eine bestimmte Aktion auszuführen",
|
||||
"custom_survey_block_1_name": "Block 1",
|
||||
"custom_survey_description": "Erstelle eine Umfrage ohne Vorlage.",
|
||||
"custom_survey_name": "Eigene Umfrage erstellen",
|
||||
"custom_survey_question_1_headline": "Was möchtest Du wissen?",
|
||||
|
||||
@@ -2248,6 +2248,7 @@
|
||||
"csat_survey_question_3_headline": "Ugh, sorry! Is there anything we can do to improve your experience?",
|
||||
"csat_survey_question_3_placeholder": "Type your answer here...",
|
||||
"cta_description": "Display information and prompt users to take a specific action",
|
||||
"custom_survey_block_1_name": "Block 1",
|
||||
"custom_survey_description": "Create a survey without template.",
|
||||
"custom_survey_name": "Start from scratch",
|
||||
"custom_survey_question_1_headline": "What would you like to know?",
|
||||
|
||||
@@ -2248,6 +2248,7 @@
|
||||
"csat_survey_question_3_headline": "Ah, désolé ! Y a-t-il quelque chose que nous puissions faire pour améliorer votre expérience ?",
|
||||
"csat_survey_question_3_placeholder": "Entrez votre réponse ici...",
|
||||
"cta_description": "Afficher des informations et inciter les utilisateurs à effectuer une action spécifique",
|
||||
"custom_survey_block_1_name": "Bloc 1",
|
||||
"custom_survey_description": "Créez une enquête sans utiliser de modèle.",
|
||||
"custom_survey_name": "Tout créer moi-même",
|
||||
"custom_survey_question_1_headline": "Que voudriez-vous savoir ?",
|
||||
|
||||
@@ -2248,6 +2248,7 @@
|
||||
"csat_survey_question_3_headline": "申し訳ありません!体験を改善するために何かできることはありますか?",
|
||||
"csat_survey_question_3_placeholder": "ここに回答を入力してください...",
|
||||
"cta_description": "情報を表示し、特定の行動を促す",
|
||||
"custom_survey_block_1_name": "ブロック1",
|
||||
"custom_survey_description": "テンプレートを使わずにアンケートを作成する。",
|
||||
"custom_survey_name": "最初から始める",
|
||||
"custom_survey_question_1_headline": "何を知りたいですか?",
|
||||
|
||||
@@ -2248,6 +2248,7 @@
|
||||
"csat_survey_question_3_headline": "Ah, foi mal! Tem algo que a gente possa fazer pra melhorar sua experiência?",
|
||||
"csat_survey_question_3_placeholder": "Digite sua resposta aqui...",
|
||||
"cta_description": "Mostrar informações e pedir para os usuários tomarem uma ação específica",
|
||||
"custom_survey_block_1_name": "Bloco 1",
|
||||
"custom_survey_description": "Crie uma pesquisa sem modelo.",
|
||||
"custom_survey_name": "Começar do zero",
|
||||
"custom_survey_question_1_headline": "O que você gostaria de saber?",
|
||||
|
||||
@@ -2248,6 +2248,7 @@
|
||||
"csat_survey_question_3_headline": "Oh, desculpe! Há algo que possamos fazer para melhorar a sua experiência?",
|
||||
"csat_survey_question_3_placeholder": "Escreva a sua resposta aqui...",
|
||||
"cta_description": "Exibir informações e solicitar aos utilizadores que tomem uma ação específica",
|
||||
"custom_survey_block_1_name": "Bloco 1",
|
||||
"custom_survey_description": "Crie um inquérito sem modelo.",
|
||||
"custom_survey_name": "Começar do zero",
|
||||
"custom_survey_question_1_headline": "O que gostaria de saber?",
|
||||
|
||||
@@ -2248,6 +2248,7 @@
|
||||
"csat_survey_question_3_headline": "Of, îmi pare rău! Există ceva ce putem face pentru a-ți îmbunătăți experiența?",
|
||||
"csat_survey_question_3_placeholder": "Tastează răspunsul aici...",
|
||||
"cta_description": "Afișează informații și solicită utilizatorilor să ia o acțiune specifică",
|
||||
"custom_survey_block_1_name": "Bloc 1",
|
||||
"custom_survey_description": "Creează un sondaj fără șablon.",
|
||||
"custom_survey_name": "Începe de la zero",
|
||||
"custom_survey_question_1_headline": "Ce ați dori să știți?",
|
||||
|
||||
@@ -2248,6 +2248,7 @@
|
||||
"csat_survey_question_3_headline": "糟糕, 对不起!我们可以做些什么来改善您的体验?",
|
||||
"csat_survey_question_3_placeholder": "在此输入您的答案...",
|
||||
"cta_description": "显示 信息 并 提示用户采取 特定行动",
|
||||
"custom_survey_block_1_name": "模块 1",
|
||||
"custom_survey_description": "创建 一个 没有 模板 的 调查。",
|
||||
"custom_survey_name": "从零开始",
|
||||
"custom_survey_question_1_headline": "你 想 知道 什么?",
|
||||
|
||||
@@ -2248,6 +2248,7 @@
|
||||
"csat_survey_question_3_headline": "唉,抱歉!我們是否有任何可以改善您體驗的地方?",
|
||||
"csat_survey_question_3_placeholder": "在此輸入您的答案...",
|
||||
"cta_description": "顯示資訊並提示使用者採取特定操作",
|
||||
"custom_survey_block_1_name": "區塊 1",
|
||||
"custom_survey_description": "建立沒有範本的問卷。",
|
||||
"custom_survey_name": "從頭開始",
|
||||
"custom_survey_question_1_headline": "您想瞭解什麼?",
|
||||
|
||||
@@ -81,7 +81,6 @@ export const QuotaModal = ({
|
||||
const [openConfirmationModal, setOpenConfirmationModal] = useState(false);
|
||||
const [openConfirmChangesInInclusionCriteria, setOpenConfirmChangesInInclusionCriteria] = useState(false);
|
||||
|
||||
// Derive questions from blocks (with fallback to legacy questions)
|
||||
const questions = useMemo(() => {
|
||||
return survey.blocks.flatMap((block) => block.elements);
|
||||
}, [survey.blocks]);
|
||||
|
||||
@@ -70,11 +70,12 @@ export const determineImageUploaderVisibility = (questionIdx: number, localSurve
|
||||
switch (questionIdx) {
|
||||
case -1: // Welcome Card
|
||||
return false;
|
||||
default:
|
||||
default: {
|
||||
// Regular Survey Question - derive questions from blocks
|
||||
const questions = localSurvey.blocks.flatMap((block) => block.elements);
|
||||
const question = questions[questionIdx];
|
||||
return (!!question && !!question.imageUrl) || (!!question && !!question.videoUrl);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ export function LogicEditor({
|
||||
const parentBlock = localSurvey.blocks?.find((block) =>
|
||||
block.elements.some((element) => element.id === question.id)
|
||||
);
|
||||
|
||||
const blockLogicFallback = parentBlock?.logicFallback;
|
||||
|
||||
const fallbackOptions = useMemo(() => {
|
||||
@@ -62,15 +63,29 @@ export function LogicEditor({
|
||||
const allQuestions = localSurvey.blocks.flatMap((b) => b.elements);
|
||||
const blocks = localSurvey.blocks;
|
||||
|
||||
// Track which blocks we've already added to avoid duplicates when a block has multiple elements
|
||||
const addedBlockIds = new Set<string>();
|
||||
|
||||
// Iterate over the questions AFTER the current question
|
||||
for (let i = questionIdx + 1; i < allQuestions.length; i++) {
|
||||
const ques = allQuestions[i];
|
||||
// Find block ID for this question
|
||||
const block = blocks.find((b) => b.elements.some((e) => e.id === ques.id));
|
||||
|
||||
if (!block) continue;
|
||||
|
||||
// Skip if we've already added this block
|
||||
if (addedBlockIds.has(block.id)) continue;
|
||||
|
||||
addedBlockIds.add(block.id);
|
||||
|
||||
// Use the first element's headline as the block label
|
||||
const firstElement = block.elements[0];
|
||||
options.push({
|
||||
icon: QUESTIONS_ICON_MAP[ques.type],
|
||||
label: getTextContent(recallToHeadline(ques.headline, localSurvey, false, "default").default ?? ""),
|
||||
value: block?.id ?? ques.id, // Block ID if blocks exist, otherwise question ID
|
||||
icon: QUESTIONS_ICON_MAP[firstElement.type],
|
||||
label: getTextContent(
|
||||
recallToHeadline(firstElement.headline, localSurvey, false, "default").default ?? ""
|
||||
),
|
||||
value: block.id,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -953,17 +953,32 @@ export const getActionTargetOptions = (
|
||||
}
|
||||
|
||||
// For jumpToBlock, we need block IDs
|
||||
// Track which blocks we've already added to avoid duplicates when a block has multiple elements
|
||||
const blocks = localSurvey.blocks ?? [];
|
||||
const questionOptions = questions.map((question) => {
|
||||
const addedBlockIds = new Set<string>();
|
||||
const questionOptions: TComboboxOption[] = [];
|
||||
|
||||
for (const question of questions) {
|
||||
// Find which block this question belongs to
|
||||
const block = blocks.find((b) => b.elements.some((e) => e.id === question.id));
|
||||
const processedHeadline = recallToHeadline(question.headline, localSurvey, false, "default");
|
||||
return {
|
||||
icon: getQuestionIconMapping(t)[question.type],
|
||||
|
||||
if (!block) continue;
|
||||
|
||||
// Skip if we've already added this block
|
||||
if (addedBlockIds.has(block.id)) continue;
|
||||
|
||||
// Mark this block as added
|
||||
addedBlockIds.add(block.id);
|
||||
|
||||
// Use the first element's headline as the block label
|
||||
const firstElement = block.elements[0];
|
||||
const processedHeadline = recallToHeadline(firstElement.headline, localSurvey, false, "default");
|
||||
questionOptions.push({
|
||||
icon: getQuestionIconMapping(t)[firstElement.type],
|
||||
label: getTextContent(processedHeadline.default ?? ""),
|
||||
value: block?.id ?? question.id, // Block ID for jumpToBlock
|
||||
};
|
||||
});
|
||||
value: block.id,
|
||||
});
|
||||
}
|
||||
|
||||
// Ending cards
|
||||
const endingCardOptions = localSurvey.endings.map((ending) => {
|
||||
|
||||
@@ -10,6 +10,7 @@ import type {
|
||||
TResponseVariables,
|
||||
} from "@formbricks/types/responses";
|
||||
import { TUploadFileConfig } from "@formbricks/types/storage";
|
||||
import { TSurveyBlockLogicAction } from "@formbricks/types/surveys/blocks";
|
||||
import { type TSurveyQuestionId } from "@formbricks/types/surveys/types";
|
||||
import { EndingCard } from "@/components/general/ending-card";
|
||||
import { ErrorComponent } from "@/components/general/error-component";
|
||||
@@ -426,7 +427,7 @@ export function Survey({
|
||||
) {
|
||||
const { jumpTarget, requiredQuestionIds, calculations } = performActions(
|
||||
localSurvey,
|
||||
logic.actions,
|
||||
logic.actions as TSurveyBlockLogicAction[], //TODO: Temporary type assertion until the survey editor poc is completed, fix properly later
|
||||
localResponseData,
|
||||
calculationResults
|
||||
);
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
import { TJsEnvironmentStateSurvey } from "@formbricks/types/js";
|
||||
import { TResponseData, TResponseVariables } from "@formbricks/types/responses";
|
||||
import { TSurveyBlockLogicAction } from "@formbricks/types/surveys/blocks";
|
||||
import { TConditionGroup, TSingleCondition } from "@formbricks/types/surveys/logic";
|
||||
import {
|
||||
TSurveyLogicAction,
|
||||
TSurveyQuestionTypeEnum,
|
||||
TSurveyVariable,
|
||||
} from "@formbricks/types/surveys/types";
|
||||
import { TSurveyQuestionTypeEnum, TSurveyVariable } from "@formbricks/types/surveys/types";
|
||||
import { evaluateLogic, isConditionGroup, performActions } from "./logic";
|
||||
|
||||
// Mock the imported function
|
||||
@@ -362,10 +359,10 @@ describe("Survey Logic", () => {
|
||||
};
|
||||
|
||||
test("performs jump action", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var1",
|
||||
objective: "jumpToQuestion",
|
||||
objective: "jumpToBlock",
|
||||
target: "q5",
|
||||
},
|
||||
];
|
||||
@@ -377,7 +374,7 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("performs require answer action", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var1",
|
||||
objective: "requireAnswer",
|
||||
@@ -392,7 +389,7 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("performs calculate action - add", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var2",
|
||||
objective: "calculate",
|
||||
@@ -407,7 +404,7 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("performs calculate action - subtract", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var2",
|
||||
objective: "calculate",
|
||||
@@ -422,7 +419,7 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("performs calculate action - multiply", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var2",
|
||||
objective: "calculate",
|
||||
@@ -437,7 +434,7 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("performs calculate action - divide", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var2",
|
||||
objective: "calculate",
|
||||
@@ -452,7 +449,7 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("handles divide by zero", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var2",
|
||||
objective: "calculate",
|
||||
@@ -467,7 +464,7 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("performs calculate action - assign", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var2",
|
||||
objective: "calculate",
|
||||
@@ -482,7 +479,7 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("performs calculate action - concat", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var1",
|
||||
objective: "calculate",
|
||||
@@ -497,7 +494,7 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("performs calculate action with question value", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var2",
|
||||
objective: "calculate",
|
||||
@@ -512,7 +509,7 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("performs calculate action with variable value", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var2",
|
||||
objective: "calculate",
|
||||
@@ -527,7 +524,7 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("performs multiple actions in order", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var2",
|
||||
objective: "calculate",
|
||||
@@ -542,7 +539,7 @@ describe("Survey Logic", () => {
|
||||
},
|
||||
{
|
||||
id: "var2",
|
||||
objective: "jumpToQuestion",
|
||||
objective: "jumpToBlock",
|
||||
target: "q5",
|
||||
},
|
||||
];
|
||||
@@ -554,15 +551,15 @@ describe("Survey Logic", () => {
|
||||
});
|
||||
|
||||
test("takes first jump target when multiple jump actions exist", () => {
|
||||
const actions: TSurveyLogicAction[] = [
|
||||
const actions: TSurveyBlockLogicAction[] = [
|
||||
{
|
||||
id: "var2",
|
||||
objective: "jumpToQuestion",
|
||||
objective: "jumpToBlock",
|
||||
target: "q2",
|
||||
},
|
||||
{
|
||||
id: "var2",
|
||||
objective: "jumpToQuestion",
|
||||
objective: "jumpToBlock",
|
||||
target: "q3",
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user