Fix Logic Jumps are not updated properly when questions are updated or deleted (#530)

* modified updateQuestion functio

* added type defs

* pnpm format

* fix LogicEditor fields not updating properly

---------

Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
This commit is contained in:
Dhruwang Jariwala
2023-07-11 22:15:54 +05:30
committed by GitHub
parent 83b94de977
commit 3f2ef3e776
3 changed files with 36 additions and 32 deletions

View File

@@ -82,6 +82,7 @@ export default function LogicEditor({
cta: ["clicked", "skipped"],
consent: ["skipped", "accepted"],
};
const logicConditions: LogicConditions = {
submitted: {
label: "is submitted",
@@ -201,10 +202,9 @@ export default function LogicEditor({
};
const deleteLogic = (logicIdx: number) => {
const newLogic = !question.logic
? []
: (question.logic as Logic[]).filter((_: any, idx: number) => idx !== logicIdx);
updateQuestion(questionIdx, { logic: newLogic });
const updatedLogic = !question.logic ? [] : JSON.parse(JSON.stringify(question.logic));
updatedLogic.splice(logicIdx, 1);
updateQuestion(questionIdx, { logic: updatedLogic });
};
const truncate = (str: string, n: number) =>
@@ -225,9 +225,7 @@ export default function LogicEditor({
<BsArrowReturnRight className="h-4 w-4" />
<p className="text-slate-700">If this answer</p>
<Select
defaultValue={logic.condition}
onValueChange={(e) => updateLogic(logicIdx, { condition: e })}>
<Select value={logic.condition} onValueChange={(e) => updateLogic(logicIdx, { condition: e })}>
<SelectTrigger className="min-w-fit flex-1">
<SelectValue placeholder="Select condition" />
</SelectTrigger>
@@ -246,9 +244,7 @@ export default function LogicEditor({
{logic.condition && logicConditions[logic.condition].values != null && (
<div className="flex-1 basis-1/5">
{!logicConditions[logic.condition].multiSelect ? (
<Select
defaultValue={logic.value}
onValueChange={(e) => updateLogic(logicIdx, { value: e })}>
<Select value={logic.value} onValueChange={(e) => updateLogic(logicIdx, { value: e })}>
<SelectTrigger>
<SelectValue placeholder="Select match type" />
</SelectTrigger>
@@ -294,7 +290,7 @@ export default function LogicEditor({
<p className="text-slate-700">skip to</p>
<Select
defaultValue={logic.destination}
value={logic.destination}
onValueChange={(e) => updateLogic(logicIdx, { destination: e })}>
<SelectTrigger className="w-fit overflow-hidden ">
<SelectValue placeholder="Select question" />

View File

@@ -1,8 +1,9 @@
"use client";
import AdvancedSettings from "@/app/environments/[environmentId]/surveys/[surveyId]/edit/AdvancedSettings";
import { getQuestionTypeName } from "@/lib/questions";
import { cn } from "@formbricks/lib/cn";
import { QuestionType, type Question } from "@formbricks/types/questions";
import { QuestionType } from "@formbricks/types/questions";
import type { Survey } from "@formbricks/types/surveys";
import { Input, Label, Switch } from "@formbricks/ui";
import {
@@ -20,18 +21,16 @@ import * as Collapsible from "@radix-ui/react-collapsible";
import { useState } from "react";
import { Draggable } from "react-beautiful-dnd";
import CTAQuestionForm from "./CTAQuestionForm";
import ConsentQuestionForm from "./ConsentQuestionForm";
import MultipleChoiceMultiForm from "./MultipleChoiceMultiForm";
import MultipleChoiceSingleForm from "./MultipleChoiceSingleForm";
import NPSQuestionForm from "./NPSQuestionForm";
import OpenQuestionForm from "./OpenQuestionForm";
import QuestionDropdown from "./QuestionMenu";
import RatingQuestionForm from "./RatingQuestionForm";
import ConsentQuestionForm from "./ConsentQuestionForm";
import AdvancedSettings from "@/app/environments/[environmentId]/surveys/[surveyId]/edit/AdvancedSettings";
interface QuestionCardProps {
localSurvey: Survey;
question: Question;
questionIdx: number;
moveQuestion: (questionIndex: number, up: boolean) => void;
updateQuestion: (questionIdx: number, updatedAttributes: any) => void;
@@ -44,7 +43,6 @@ interface QuestionCardProps {
export default function QuestionCard({
localSurvey,
question,
questionIdx,
moveQuestion,
updateQuestion,
@@ -54,6 +52,7 @@ export default function QuestionCard({
setActiveQuestionId,
lastQuestion,
}: QuestionCardProps) {
const question = localSurvey.questions[questionIdx];
const open = activeQuestionId === question.id;
const [openAdvanced, setOpenAdvanced] = useState(question.logic && question.logic.length > 0);
return (

View File

@@ -32,35 +32,45 @@ export default function QuestionsView({
}, {});
}, []);
const handleQuestionLogicChange = (survey: Survey, compareId: string, updatedId: string): Survey => {
survey.questions.forEach((question) => {
if (!question.logic) return;
question.logic.forEach((rule) => {
if (rule.destination === compareId) {
rule.destination = updatedId;
}
});
});
return survey;
};
const updateQuestion = (questionIdx: number, updatedAttributes: any) => {
const updatedSurvey = JSON.parse(JSON.stringify(localSurvey));
updatedSurvey.questions[questionIdx] = {
...updatedSurvey.questions[questionIdx],
...updatedAttributes,
};
setLocalSurvey(updatedSurvey);
let updatedSurvey = JSON.parse(JSON.stringify(localSurvey));
if ("id" in updatedAttributes) {
// if the survey whose id is to be changed is linked to logic of any other survey then changing it
const initialQuestionId = updatedSurvey.questions[questionIdx].id;
updatedSurvey = handleQuestionLogicChange(updatedSurvey, initialQuestionId, updatedAttributes.id);
// relink the question to internal Id
internalQuestionIdMap[updatedAttributes.id] =
internalQuestionIdMap[localSurvey.questions[questionIdx].id];
delete internalQuestionIdMap[localSurvey.questions[questionIdx].id];
setActiveQuestionId(updatedAttributes.id);
}
updatedSurvey.questions[questionIdx] = {
...updatedSurvey.questions[questionIdx],
...updatedAttributes,
};
setLocalSurvey(updatedSurvey);
};
const deleteQuestion = (questionIdx: number) => {
const questionId = localSurvey.questions[questionIdx].id;
const updatedSurvey: Survey = JSON.parse(JSON.stringify(localSurvey));
let updatedSurvey: Survey = JSON.parse(JSON.stringify(localSurvey));
updatedSurvey.questions.splice(questionIdx, 1);
updatedSurvey.questions.forEach((question) => {
if (!question.logic) return;
question.logic.forEach((rule) => {
if (rule.destination === questionId) {
rule.destination = "end";
}
});
});
updatedSurvey = handleQuestionLogicChange(updatedSurvey, questionId, "end");
setLocalSurvey(updatedSurvey);
delete internalQuestionIdMap[questionId];
@@ -141,7 +151,6 @@ export default function QuestionsView({
<QuestionCard
key={internalQuestionIdMap[question.id]}
localSurvey={localSurvey}
question={question}
questionIdx={questionIdx}
moveQuestion={moveQuestion}
updateQuestion={updateQuestion}