mirror of
https://github.com/formbricks/formbricks.git
synced 2026-02-14 02:31:34 -06:00
fix: survey preview stuck in sending (#4941)
This commit is contained in:
@@ -231,6 +231,7 @@ export const ProjectSettings = ({
|
||||
<p className="text-sm text-slate-400">{t("common.preview")}</p>
|
||||
<div className="z-0 h-3/4 w-3/4">
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={previewSurvey(projectName || "my Product", t)}
|
||||
styling={{ brandColor: { light: brandColor } }}
|
||||
isBrandingEnabled={false}
|
||||
|
||||
@@ -243,7 +243,6 @@ export const SurveyEditor = ({
|
||||
environment={environment}
|
||||
previewType={localSurvey.type === "app" ? "modal" : "fullwidth"}
|
||||
languageCode={selectedLanguageCode}
|
||||
onFileUpload={async (file) => file.name}
|
||||
/>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
@@ -170,14 +170,14 @@ export const LinkSurvey = ({
|
||||
PRIVACY_URL={PRIVACY_URL}
|
||||
isBrandingEnabled={project.linkSurveyBranding}>
|
||||
<SurveyInline
|
||||
apiHost={!isPreview ? webAppUrl : undefined}
|
||||
environmentId={!isPreview ? survey.environmentId : undefined}
|
||||
apiHost={webAppUrl}
|
||||
environmentId={survey.environmentId}
|
||||
isPreviewMode={isPreview}
|
||||
survey={survey}
|
||||
styling={determineStyling()}
|
||||
languageCode={languageCode}
|
||||
isBrandingEnabled={project.linkSurveyBranding}
|
||||
shouldResetQuestionId={false}
|
||||
onFileUpload={isPreview ? async (file) => `https://formbricks.com/${file.name}` : undefined}
|
||||
// eslint-disable-next-line jsx-a11y/no-autofocus -- need it as focus behaviour is different in normal surveys and survey preview
|
||||
autoFocus={autoFocus}
|
||||
prefillResponseData={prefillValue}
|
||||
|
||||
@@ -84,7 +84,6 @@ export const TemplateContainerWithPreview = ({
|
||||
project={project}
|
||||
environment={environment}
|
||||
languageCode={"default"}
|
||||
onFileUpload={async (file) => file.name}
|
||||
/>
|
||||
)}
|
||||
</aside>
|
||||
|
||||
@@ -9,9 +9,7 @@ import { useTranslate } from "@tolgee/react";
|
||||
import { Variants, motion } from "framer-motion";
|
||||
import { ExpandIcon, MonitorIcon, ShrinkIcon, SmartphoneIcon } from "lucide-react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { TJsFileUploadParams } from "@formbricks/types/js";
|
||||
import { TProjectStyling } from "@formbricks/types/project";
|
||||
import { TUploadFileConfig } from "@formbricks/types/storage";
|
||||
import { TSurvey, TSurveyQuestionId, TSurveyStyling } from "@formbricks/types/surveys/types";
|
||||
import { Modal } from "./components/modal";
|
||||
import { TabOption } from "./components/tab-option";
|
||||
@@ -25,7 +23,6 @@ interface PreviewSurveyProps {
|
||||
project: Project;
|
||||
environment: Pick<Environment, "id" | "appSetupCompleted">;
|
||||
languageCode: string;
|
||||
onFileUpload: (file: TJsFileUploadParams["file"], config?: TUploadFileConfig) => Promise<string>;
|
||||
}
|
||||
|
||||
let surveyNameTemp: string;
|
||||
@@ -66,7 +63,6 @@ export const PreviewSurvey = ({
|
||||
project,
|
||||
environment,
|
||||
languageCode,
|
||||
onFileUpload,
|
||||
}: PreviewSurveyProps) => {
|
||||
const [isModalOpen, setIsModalOpen] = useState(true);
|
||||
const [isFullScreenPreview, setIsFullScreenPreview] = useState(false);
|
||||
@@ -265,11 +261,11 @@ export const PreviewSurvey = ({
|
||||
borderRadius={styling?.roundness ?? 8}
|
||||
background={styling?.cardBackgroundColor?.light}>
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={survey}
|
||||
isBrandingEnabled={project.inAppSurveyBranding}
|
||||
isRedirectDisabled={true}
|
||||
languageCode={languageCode}
|
||||
onFileUpload={onFileUpload}
|
||||
styling={styling}
|
||||
isCardBorderVisible={!styling.highlightBorderColor?.light}
|
||||
onClose={handlePreviewModalClose}
|
||||
@@ -288,9 +284,9 @@ export const PreviewSurvey = ({
|
||||
</div>
|
||||
<div className="z-10 w-full max-w-md rounded-lg border border-transparent">
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={{ ...survey, type: "link" }}
|
||||
isBrandingEnabled={project.linkSurveyBranding}
|
||||
onFileUpload={onFileUpload}
|
||||
languageCode={languageCode}
|
||||
responseCount={42}
|
||||
styling={styling}
|
||||
@@ -367,11 +363,11 @@ export const PreviewSurvey = ({
|
||||
borderRadius={styling.roundness ?? 8}
|
||||
background={styling.cardBackgroundColor?.light}>
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={survey}
|
||||
isBrandingEnabled={project.inAppSurveyBranding}
|
||||
isRedirectDisabled={true}
|
||||
languageCode={languageCode}
|
||||
onFileUpload={onFileUpload}
|
||||
styling={styling}
|
||||
isCardBorderVisible={!styling.highlightBorderColor?.light}
|
||||
onClose={handlePreviewModalClose}
|
||||
@@ -394,10 +390,10 @@ export const PreviewSurvey = ({
|
||||
</div>
|
||||
<div className="z-0 w-full max-w-4xl rounded-lg border-transparent">
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={{ ...survey, type: "link" }}
|
||||
isBrandingEnabled={project.linkSurveyBranding}
|
||||
isRedirectDisabled={true}
|
||||
onFileUpload={onFileUpload}
|
||||
languageCode={languageCode}
|
||||
responseCount={42}
|
||||
styling={styling}
|
||||
|
||||
@@ -162,6 +162,7 @@ export const ThemeStylingPreviewSurvey = ({
|
||||
borderRadius={project.styling.roundness ?? 8}>
|
||||
<Fragment key={surveyFormKey}>
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={{ ...survey, type: "app" }}
|
||||
isBrandingEnabled={project.inAppSurveyBranding}
|
||||
isRedirectDisabled={true}
|
||||
@@ -187,6 +188,7 @@ export const ThemeStylingPreviewSurvey = ({
|
||||
key={surveyFormKey}
|
||||
className={`${project.logo?.url && !project.styling.isLogoHidden && !isFullScreenPreview ? "mt-12" : ""} z-0 w-full max-w-md rounded-lg p-4`}>
|
||||
<SurveyInline
|
||||
isPreviewMode={true}
|
||||
survey={{ ...survey, type: "link" }}
|
||||
isBrandingEnabled={project.linkSurveyBranding}
|
||||
isRedirectDisabled={true}
|
||||
|
||||
@@ -36,6 +36,7 @@ interface VariableStackEntry {
|
||||
export function Survey({
|
||||
apiHost,
|
||||
environmentId,
|
||||
isPreviewMode = false,
|
||||
userId,
|
||||
contactId,
|
||||
mode,
|
||||
@@ -150,7 +151,6 @@ export function Survey({
|
||||
return localSurvey.questions[0]?.id;
|
||||
});
|
||||
const [showError, setShowError] = useState(false);
|
||||
// flag state to store whether response processing has been completed or not, we ignore this check for survey editor preview and link survey preview where getSetIsResponseSendingFinished is undefined
|
||||
const [isResponseSendingFinished, setIsResponseSendingFinished] = useState(
|
||||
!getSetIsResponseSendingFinished
|
||||
);
|
||||
@@ -182,6 +182,11 @@ export function Survey({
|
||||
};
|
||||
|
||||
const onFileUploadApi = async (file: TJsFileUploadParams["file"], params?: TUploadFileConfig) => {
|
||||
if (isPreviewMode) {
|
||||
// return mock url since an url is required for the preview
|
||||
return `https://example.com/${file.name}`;
|
||||
}
|
||||
|
||||
if (!apiClient) {
|
||||
throw new Error("apiClient not initialized");
|
||||
}
|
||||
@@ -206,6 +211,17 @@ export function Survey({
|
||||
}, [questionId]);
|
||||
|
||||
const createDisplay = useCallback(async () => {
|
||||
// Skip display creation in preview mode but still trigger the onDisplayCreated callback
|
||||
if (isPreviewMode) {
|
||||
if (onDisplayCreated) {
|
||||
onDisplayCreated();
|
||||
}
|
||||
if (onDisplay) {
|
||||
onDisplay();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (apiClient && surveyState && responseQueue) {
|
||||
try {
|
||||
const display = await apiClient.createDisplay({
|
||||
@@ -229,7 +245,17 @@ export function Survey({
|
||||
console.error("error creating display: ", err);
|
||||
}
|
||||
}
|
||||
}, [apiClient, surveyState, responseQueue, survey.id, userId, contactId, onDisplayCreated]);
|
||||
}, [
|
||||
apiClient,
|
||||
surveyState,
|
||||
responseQueue,
|
||||
survey.id,
|
||||
userId,
|
||||
contactId,
|
||||
onDisplayCreated,
|
||||
isPreviewMode,
|
||||
onDisplay,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
// call onDisplay when component is mounted
|
||||
@@ -385,6 +411,32 @@ export function Survey({
|
||||
|
||||
const onResponseCreateOrUpdate = useCallback(
|
||||
(responseUpdate: TResponseUpdate) => {
|
||||
// Always trigger the onResponse callback even in preview mode
|
||||
if (!apiHost || !environmentId) {
|
||||
onResponse?.({
|
||||
data: responseUpdate.data,
|
||||
ttc: responseUpdate.ttc,
|
||||
finished: responseUpdate.finished,
|
||||
variables: responseUpdate.variables,
|
||||
language: responseUpdate.language,
|
||||
endingId: responseUpdate.endingId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip response creation in preview mode but still trigger the onResponseCreated callback
|
||||
if (isPreviewMode) {
|
||||
if (onResponseCreated) {
|
||||
onResponseCreated();
|
||||
}
|
||||
|
||||
// When in preview mode, set isResponseSendingFinished to true if the response is finished
|
||||
if (responseUpdate.finished) {
|
||||
setIsResponseSendingFinished(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (surveyState && responseQueue) {
|
||||
if (contactId) {
|
||||
surveyState.updateContactId(contactId);
|
||||
@@ -415,7 +467,20 @@ export function Survey({
|
||||
}
|
||||
}
|
||||
},
|
||||
[surveyState, responseQueue, contactId, userId, survey, action, hiddenFieldsRecord, onResponseCreated]
|
||||
[
|
||||
apiHost,
|
||||
environmentId,
|
||||
isPreviewMode,
|
||||
surveyState,
|
||||
responseQueue,
|
||||
contactId,
|
||||
userId,
|
||||
survey,
|
||||
action,
|
||||
hiddenFieldsRecord,
|
||||
onResponseCreated,
|
||||
onResponse,
|
||||
]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -446,25 +511,14 @@ export function Survey({
|
||||
onChange(surveyResponseData);
|
||||
onChangeVariables(calculatedVariables);
|
||||
|
||||
if (apiHost && environmentId) {
|
||||
onResponseCreateOrUpdate({
|
||||
data: surveyResponseData,
|
||||
ttc: responsettc,
|
||||
finished,
|
||||
variables: calculatedVariables,
|
||||
language: selectedLanguage,
|
||||
endingId,
|
||||
});
|
||||
} else {
|
||||
onResponse?.({
|
||||
data: surveyResponseData,
|
||||
ttc: responsettc,
|
||||
finished,
|
||||
variables: calculatedVariables,
|
||||
language: selectedLanguage,
|
||||
endingId,
|
||||
});
|
||||
}
|
||||
onResponseCreateOrUpdate({
|
||||
data: surveyResponseData,
|
||||
ttc: responsettc,
|
||||
finished,
|
||||
variables: calculatedVariables,
|
||||
language: selectedLanguage,
|
||||
endingId,
|
||||
});
|
||||
|
||||
if (nextQuestionId) {
|
||||
setQuestionId(nextQuestionId);
|
||||
@@ -573,7 +627,7 @@ export function Survey({
|
||||
onBack={onBack}
|
||||
ttc={ttc}
|
||||
setTtc={setTtc}
|
||||
onFileUpload={apiHost && environmentId ? onFileUploadApi : onFileUpload!}
|
||||
onFileUpload={onFileUpload ?? onFileUploadApi}
|
||||
isFirstQuestion={question.id === localSurvey.questions[0]?.id}
|
||||
skipPrefilled={skipPrefilled}
|
||||
prefilledQuestionValue={getQuestionPrefillData(question.id, offset)}
|
||||
|
||||
@@ -45,6 +45,7 @@ export interface SurveyModalProps extends SurveyBaseProps {
|
||||
export interface SurveyContainerProps extends Omit<SurveyBaseProps, "onFileUpload"> {
|
||||
apiHost?: string;
|
||||
environmentId?: string;
|
||||
isPreviewMode?: boolean;
|
||||
userId?: string;
|
||||
contactId?: string;
|
||||
onDisplayCreated?: () => void | Promise<void>;
|
||||
|
||||
Reference in New Issue
Block a user