fixes UI issues

This commit is contained in:
pandeymangg
2025-11-21 15:26:55 +05:30
parent 1e6c7609b6
commit d7e537f699
12 changed files with 43 additions and 52 deletions

View File

@@ -1385,6 +1385,7 @@ checksums:
environments/surveys/edit/move_question_to_block: e8d7ef1e2f727921cb7f5788849492ad
environments/surveys/edit/multiply: 89a0bb629167f97750ae1645a46ced0d
environments/surveys/edit/needed_for_self_hosted_cal_com_instance: d241e72f0332177d32ce6c35070757dc
environments/surveys/edit/next_block: 53eaa5b1c9333455ab1e99bedd222ba2
environments/surveys/edit/next_button_label: e23522dd38f3eabeeccd3f48f32b73a8
environments/surveys/edit/next_question: 2e0f1ea264fb4bfcb8378b2b0cf7c18f
environments/surveys/edit/no_hidden_fields_yet_add_first_one_below: 9cc6cab3a6a42dbf835215897b5b8516

View File

@@ -1470,8 +1470,8 @@
"move_question_to_block": "Frage in Block verschieben",
"multiply": "Multiplizieren *",
"needed_for_self_hosted_cal_com_instance": "Benötigt für eine selbstgehostete Cal.com-Instanz",
"next_block": "Nächster Block",
"next_button_label": "Beschriftung der Schaltfläche \"Weiter\"",
"next_question": "Nächste Frage",
"no_hidden_fields_yet_add_first_one_below": "Noch keine versteckten Felder. Füge das erste unten hinzu.",
"no_images_found_for": "Keine Bilder gefunden für ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "Keine Sprachen gefunden. Füge die erste hinzu, um loszulegen.",

View File

@@ -1470,8 +1470,8 @@
"move_question_to_block": "Move question to block",
"multiply": "Multiply *",
"needed_for_self_hosted_cal_com_instance": "Needed for a self-hosted Cal.com instance",
"next_block": "Next block",
"next_button_label": "\"Next\" button label",
"next_question": "Next question",
"no_hidden_fields_yet_add_first_one_below": "No hidden fields yet. Add the first one below.",
"no_images_found_for": "No images found for ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "No languages found. Add the first one to get started.",

View File

@@ -1470,8 +1470,8 @@
"move_question_to_block": "Déplacer la question vers le bloc",
"multiply": "Multiplier *",
"needed_for_self_hosted_cal_com_instance": "Nécessaire pour une instance Cal.com auto-hébergée",
"next_block": "Bloc suivant",
"next_button_label": "Libellé du bouton «Suivant»",
"next_question": "Question suivante",
"no_hidden_fields_yet_add_first_one_below": "Aucun champ caché pour le moment. Ajoutez le premier ci-dessous.",
"no_images_found_for": "Aucune image trouvée pour ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "Aucune langue trouvée. Ajoutez la première pour commencer.",

View File

@@ -1470,8 +1470,8 @@
"move_question_to_block": "質問をブロックに移動",
"multiply": "乗算 *",
"needed_for_self_hosted_cal_com_instance": "セルフホストのCal.comインスタンスに必要",
"next_block": "次のブロック",
"next_button_label": "「次へ」ボタンのラベル",
"next_question": "次の質問",
"no_hidden_fields_yet_add_first_one_below": "まだ非表示フィールドがありません。以下で最初のものを追加してください。",
"no_images_found_for": "''{query}'' の画像が見つかりません",
"no_languages_found_add_first_one_to_get_started": "言語が見つかりません。始めるには、最初のものを追加してください。",

View File

@@ -1470,8 +1470,8 @@
"move_question_to_block": "Mover pergunta para o bloco",
"multiply": "Multiplicar *",
"needed_for_self_hosted_cal_com_instance": "Necessário para uma instância auto-hospedada do Cal.com",
"next_block": "Próximo bloco",
"next_button_label": "Próximo",
"next_question": "próxima pergunta",
"no_hidden_fields_yet_add_first_one_below": "Ainda não há campos ocultos. Adicione o primeiro abaixo.",
"no_images_found_for": "Nenhuma imagem encontrada para ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "Nenhum idioma encontrado. Adicione o primeiro para começar.",

View File

@@ -1470,8 +1470,8 @@
"move_question_to_block": "Mover pergunta para o bloco",
"multiply": "Multiplicar *",
"needed_for_self_hosted_cal_com_instance": "Necessário para uma instância auto-hospedada do Cal.com",
"next_block": "Bloco seguinte",
"next_button_label": "Rótulo do botão \"Seguinte\"",
"next_question": "Próxima pergunta",
"no_hidden_fields_yet_add_first_one_below": "Ainda não há campos ocultos. Adicione o primeiro abaixo.",
"no_images_found_for": "Não foram encontradas imagens para ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "Nenhuma língua encontrada. Adicione a primeira para começar.",

View File

@@ -1470,8 +1470,8 @@
"move_question_to_block": "Mută întrebarea în bloc",
"multiply": "Multiplicare",
"needed_for_self_hosted_cal_com_instance": "Necesar pentru un exemplu autogăzduit Cal.com",
"next_block": "Blocul următor",
"next_button_label": "Etichetă buton \"Următorul\"",
"next_question": "Întrebarea următoare",
"no_hidden_fields_yet_add_first_one_below": "Nu există încă câmpuri ascunse. Adăugați primul mai jos.",
"no_images_found_for": "Nicio imagine găsită pentru ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "Nu s-au găsit limbi. Adaugă prima pentru a începe.",

View File

@@ -1470,8 +1470,8 @@
"move_question_to_block": "将问题移动到区块",
"multiply": "乘 *",
"needed_for_self_hosted_cal_com_instance": "需要用于 自建 Cal.com 实例",
"next_block": "下一块",
"next_button_label": "\"下一步\" 按钮标签",
"next_question": "下一个问题",
"no_hidden_fields_yet_add_first_one_below": "还没有隐藏字段。 在下面添加第一个。",
"no_images_found_for": "未找到与 \"{query}\" 相关的图片",
"no_languages_found_add_first_one_to_get_started": "没有找到语言。添加第一个以开始。",

View File

@@ -1470,8 +1470,8 @@
"move_question_to_block": "將問題移至區塊",
"multiply": "乘 *",
"needed_for_self_hosted_cal_com_instance": "自行託管 Cal.com 執行個體時需要",
"next_block": "下一個區塊",
"next_button_label": "「下一步」按鈕標籤",
"next_question": "下一個問題",
"no_hidden_fields_yet_add_first_one_below": "尚無隱藏欄位。在下方新增第一個隱藏欄位。",
"no_images_found_for": "找不到「'{'query'}'」的圖片",
"no_languages_found_add_first_one_to_get_started": "找不到語言。新增第一個語言以開始使用。",

View File

@@ -1,7 +1,7 @@
"use client";
import { ArrowRightIcon } from "lucide-react";
import { ReactElement, useMemo } from "react";
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { TSurveyBlockLogic } from "@formbricks/types/surveys/blocks";
import { TSurveyBlock } from "@formbricks/types/surveys/blocks";
@@ -10,7 +10,6 @@ import { getTextContent } from "@formbricks/types/surveys/validation";
import { recallToHeadline } from "@/lib/utils/recall";
import { LogicEditorActions } from "@/modules/survey/editor/components/logic-editor-actions";
import { LogicEditorConditions } from "@/modules/survey/editor/components/logic-editor-conditions";
import { getQuestionIconMap } from "@/modules/survey/lib/questions";
import {
Select,
SelectContent,
@@ -41,39 +40,23 @@ export function LogicEditor({
isLast,
}: LogicEditorProps) {
const { t } = useTranslation();
const QUESTIONS_ICON_MAP = getQuestionIconMap(t);
const blockLogicFallback = block.logicFallback;
const fallbackOptions = useMemo(() => {
let options: {
icon?: ReactElement;
label: string;
value: string;
}[] = [];
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 elements AFTER the current block
// Add blocks AFTER the current block
for (let i = blockIdx + 1; i < blocks.length; i++) {
const currentBlock = blocks[i];
if (addedBlockIds.has(currentBlock.id)) continue;
addedBlockIds.add(currentBlock.id);
// Use the first element's headline as the block label
const firstElement = currentBlock.elements[0];
if (!firstElement) continue;
options.push({
icon: QUESTIONS_ICON_MAP[firstElement.type],
label: getTextContent(
recallToHeadline(firstElement.headline, localSurvey, false, "default").default ?? ""
),
label: currentBlock.name,
value: currentBlock.id,
});
}
@@ -92,7 +75,7 @@ export function LogicEditor({
});
return options;
}, [localSurvey, blockIdx, QUESTIONS_ICON_MAP, t]);
}, [localSurvey, blockIdx, t]);
return (
<div className="flex w-full min-w-full grow flex-col gap-4 overflow-x-auto pb-2 text-sm">
@@ -133,15 +116,12 @@ export function LogicEditor({
</SelectTrigger>
<SelectContent>
<SelectItem key="fallback_default_selection" value={"defaultSelection"}>
{t("environments.surveys.edit.next_question")}
{t("environments.surveys.edit.next_block")}
</SelectItem>
{fallbackOptions.map((option) => (
<SelectItem key={`fallback_${option.value}`} value={option.value}>
<div className="flex items-center gap-2">
{option.icon}
{option.label}
</div>
{option.label}
</SelectItem>
))}
</SelectContent>

View File

@@ -26,7 +26,7 @@ import { isConditionGroup } from "@/lib/surveyLogic/utils";
import { recallToHeadline } from "@/lib/utils/recall";
import { findElementLocation } from "@/modules/survey/editor/lib/blocks";
import { getElementsFromBlocks } from "@/modules/survey/lib/client-utils";
import { getQuestionTypes } from "@/modules/survey/lib/questions";
import { getQuestionTypes, getTSurveyQuestionTypeEnumName } from "@/modules/survey/lib/questions";
import { TComboboxGroupedOption, TComboboxOption } from "@/modules/ui/components/input-combo-box";
import { TLogicRuleOption, getLogicRules } from "./logic-rule-engine";
@@ -106,6 +106,23 @@ const getQuestionIconMapping = (t: TFunction) =>
{}
);
const getElementHeadline = (
localSurvey: TSurvey,
element: TSurveyElement,
languageCode: string,
t: TFunction
): string => {
const headlineData = recallToHeadline(element.headline, localSurvey, false, languageCode);
const headlineText = headlineData[languageCode];
if (headlineText) {
const textContent = getTextContent(headlineText);
if (textContent.length > 0) {
return textContent;
}
}
return getTSurveyQuestionTypeEnumName(element.type, t) ?? "";
};
export const getConditionValueOptions = (
localSurvey: TSurvey,
t: TFunction,
@@ -128,9 +145,9 @@ export const getConditionValueOptions = (
allElements.forEach((element) => {
if (element.type === TSurveyElementTypeEnum.Matrix) {
const elementHeadline = getElementHeadline(localSurvey, element, "default", t);
// Rows submenu
const processedHeadline = recallToHeadline(element.headline, localSurvey, false, "default");
const elementHeadline = getTextContent(processedHeadline.default ?? "");
const rows = element.rows.map((row, rowIdx) => {
const processedLabel = recallToHeadline(row.label, localSurvey, false, "default");
return {
@@ -169,9 +186,7 @@ export const getConditionValueOptions = (
} else {
elementOptions.push({
icon: getQuestionIconMapping(t)[element.type],
label: getTextContent(
recallToHeadline(element.headline, localSurvey, false, "default").default ?? ""
),
label: getElementHeadline(localSurvey, element, "default", t),
value: element.id,
meta: {
type: "question",
@@ -715,10 +730,9 @@ export const getMatchValueProps = (
const allowedElements = elements.filter((element) => allowedElementTypes.includes(element.type));
const elementOptions = allowedElements.map((element) => {
const processedHeadline = recallToHeadline(element.headline, localSurvey, false, "default");
return {
icon: getQuestionIconMapping(t)[element.type],
label: getTextContent(processedHeadline.default ?? ""),
label: getElementHeadline(localSurvey, element, "default", t),
value: element.id,
meta: {
type: "question",
@@ -790,10 +804,9 @@ export const getMatchValueProps = (
);
const elementOptions = allowedElements.map((element) => {
const processedHeadline = recallToHeadline(element.headline, localSurvey, false, "default");
return {
icon: getQuestionIconMapping(t)[element.type],
label: getTextContent(processedHeadline.default ?? ""),
label: getElementHeadline(localSurvey, element, "default", t),
value: element.id,
meta: {
type: "question",
@@ -871,10 +884,9 @@ export const getMatchValueProps = (
const allowedElements = elements.filter((element) => allowedElementTypes.includes(element.type));
const elementOptions = allowedElements.map((element) => {
const processedHeadline = recallToHeadline(element.headline, localSurvey, false, "default");
return {
icon: getQuestionIconMapping(t)[element.type],
label: getTextContent(processedHeadline.default ?? ""),
label: getElementHeadline(localSurvey, element, "default", t),
value: element.id,
meta: {
type: "question",
@@ -967,11 +979,10 @@ export const getActionTargetOptions = (
// Return element IDs for requireAnswer
return nonRequiredElements.map((element) => {
const processedHeadline = recallToHeadline(element.headline, localSurvey, false, "default");
return {
icon: getQuestionIconMapping(t)[element.type],
label: getTextContent(processedHeadline.default ?? ""),
value: element.id, // Element ID
label: getElementHeadline(localSurvey, element, "default", t),
value: element.id,
};
});
}
@@ -1114,10 +1125,9 @@ export const getActionValueOptions = (
);
const elementOptions = allowedElements.map((element) => {
const processedHeadline = recallToHeadline(element.headline, localSurvey, false, "default");
return {
icon: getQuestionIconMapping(t)[element.type],
label: getTextContent(processedHeadline.default ?? ""),
label: getElementHeadline(localSurvey, element, "default", t),
value: element.id,
meta: {
type: "question",