Fix Preview on Delete in Survey Builder & Fix Button Text on light brand color (#284)

* Fix Preview on Delete in Survey Builder
* Fix Button Text on light brand color

---------

Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
This commit is contained in:
Moritz Rengert
2023-05-19 08:46:46 +02:00
committed by GitHub
parent 41443267c9
commit 953f04b42a
19 changed files with 162 additions and 69 deletions
@@ -42,8 +42,10 @@ export default function PreviewSurvey({
setProgress(calculateProgress(questions, lastActiveQuestionId));
}
function calculateProgress(questions, id) {
const elementIdx = questions.findIndex((e) => e.id === id);
function calculateProgress(questions, activeQuestionId) {
if (activeQuestionId === "thank-you-card") return 1;
const elementIdx = questions.findIndex((e) => e.id === activeQuestionId);
return elementIdx / questions.length;
}
}, [activeQuestionId, lastActiveQuestionId, questions]);
@@ -22,18 +22,29 @@ export default function QuestionDropdown({
<EllipsisHorizontalIcon className="h-5 w-5 text-slate-600 focus:outline-none active:outline-none" />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem className="justify-between" onClick={() => deleteQuestion(questionIdx)}>
<DropdownMenuItem
className="justify-between"
onClick={(e) => {
e.stopPropagation();
deleteQuestion(questionIdx);
}}>
Delete <TrashIcon className="ml-3 h-4" />
</DropdownMenuItem>
<DropdownMenuItem
className="justify-between"
onClick={() => moveQuestion(questionIdx, true)}
onClick={(e) => {
e.stopPropagation();
moveQuestion(questionIdx, true);
}}
disabled={questionIdx == 0}>
Move up <ArrowUpIcon className="ml-3 h-4" />
</DropdownMenuItem>
<DropdownMenuItem
className="justify-between"
onClick={() => moveQuestion(questionIdx, false)}
onClick={(e) => {
e.stopPropagation();
moveQuestion(questionIdx, false);
}}
disabled={lastQuestion}>
Move down
<ArrowDownIcon className="h-4" />
@@ -48,10 +48,22 @@ export default function QuestionsView({
};
const deleteQuestion = (questionIdx: number) => {
const questionId = localSurvey.questions[questionIdx].id;
const updatedSurvey = JSON.parse(JSON.stringify(localSurvey));
updatedSurvey.questions.splice(questionIdx, 1);
setLocalSurvey(updatedSurvey);
delete internalQuestionIdMap[localSurvey.questions[questionIdx].id];
delete internalQuestionIdMap[questionId];
if (questionId === activeQuestionId) {
if (questionIdx < localSurvey.questions.length - 1) {
setActiveQuestionId(localSurvey.questions[questionIdx + 1].id);
} else if (localSurvey.thankYouCard.enabled) {
setActiveQuestionId("thank-you-card");
} else {
setActiveQuestionId(localSurvey.questions[questionIdx - 1].id);
}
}
};
const addQuestion = (question: any) => {
+6 -1
View File
@@ -1,6 +1,8 @@
import type { CTAQuestion } from "@formbricks/types/questions";
import Headline from "./Headline";
import HtmlBody from "./HtmlBody";
import { cn } from "@/../../packages/lib/cn";
import { isLight } from "@/lib/utils";
interface CTAQuestionProps {
question: CTAQuestion;
@@ -35,7 +37,10 @@ export default function CTAQuestion({ question, onSubmit, lastQuestion, brandCol
}
onSubmit({ [question.id]: "clicked" });
}}
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
className={cn(
"flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2",
isLight(brandColor) ? "text-black" : "text-white"
)}
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
@@ -3,6 +3,7 @@ import { cn } from "@formbricks/lib/cn";
import type { MultipleChoiceMultiQuestion } from "@formbricks/types/questions";
import Headline from "./Headline";
import Subheader from "./Subheader";
import SubmitButton from "@/components/preview/SubmitButton";
interface MultipleChoiceMultiProps {
question: MultipleChoiceMultiQuestion;
@@ -93,12 +94,7 @@ export default function MultipleChoiceMultiQuestion({
/>
<div className="mt-4 flex w-full justify-between">
<div></div>
<button
type="submit"
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
<SubmitButton {...{ question, lastQuestion, brandColor }} />
</div>
</form>
);
@@ -3,6 +3,7 @@ import type { MultipleChoiceSingleQuestion } from "@formbricks/types/questions";
import { useState } from "react";
import Headline from "./Headline";
import Subheader from "./Subheader";
import SubmitButton from "@/components/preview/SubmitButton";
interface MultipleChoiceSingleProps {
question: MultipleChoiceSingleQuestion;
@@ -69,12 +70,7 @@ export default function MultipleChoiceSingleQuestion({
</div>
<div className="mt-4 flex w-full justify-between">
<div></div>
<button
type="submit"
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
<SubmitButton {...{ question, lastQuestion, brandColor }} />
</div>
</form>
);
+2 -6
View File
@@ -3,6 +3,7 @@ import { cn } from "@formbricks/lib/cn";
import type { NPSQuestion } from "@formbricks/types/questions";
import Headline from "./Headline";
import Subheader from "./Subheader";
import SubmitButton from "@/components/preview/SubmitButton";
interface NPSQuestionProps {
question: NPSQuestion;
@@ -69,12 +70,7 @@ export default function NPSQuestion({ question, onSubmit, lastQuestion, brandCol
{!question.required && (
<div className="mt-4 flex w-full justify-between">
<div></div>
<button
type="submit"
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
<SubmitButton {...{ question, lastQuestion, brandColor }} />
</div>
)}
</form>
@@ -2,6 +2,7 @@ import type { OpenTextQuestion } from "@formbricks/types/questions";
import { useState } from "react";
import Headline from "./Headline";
import Subheader from "./Subheader";
import SubmitButton from "@/components/preview/SubmitButton";
interface OpenTextQuestionProps {
question: OpenTextQuestion;
@@ -44,12 +45,7 @@ export default function OpenTextQuestion({
</div>
<div className="mt-4 flex w-full justify-between">
<div></div>
<button
type="submit"
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
<SubmitButton {...{ question, lastQuestion, brandColor }} />
</div>
</form>
);
@@ -17,6 +17,7 @@ import {
TiredFace,
WearyFace,
} from "../Smileys";
import SubmitButton from "@/components/preview/SubmitButton";
interface RatingQuestionProps {
question: RatingQuestion;
@@ -130,12 +131,7 @@ export default function RatingQuestion({
{!question.required && (
<div className="mt-4 flex w-full justify-between">
<div></div>
<button
type="submit"
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
<SubmitButton {...{ question, lastQuestion, brandColor }} />
</div>
)}
</form>
@@ -0,0 +1,17 @@
import { cn } from "@/../../packages/lib/cn";
import { isLight } from "@/lib/utils";
function SubmitButton({ question, lastQuestion, brandColor }) {
return (
<button
type="submit"
className={cn(
"flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2",
isLight(brandColor) ? "text-black" : "text-white"
)}
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
);
}
export default SubmitButton;
+14
View File
@@ -39,3 +39,17 @@ export const scrollToTop = () => {
behavior: "smooth",
});
};
export function isLight(color) {
let r, g, b;
if (color.length === 4) {
r = parseInt(color[1] + color[1], 16);
g = parseInt(color[2] + color[2], 16);
b = parseInt(color[3] + color[3], 16);
} else if (color.length === 7) {
r = parseInt(color[1] + color[2], 16);
g = parseInt(color[3] + color[4], 16);
b = parseInt(color[5] + color[6], 16);
}
return r * 0.299 + g * 0.587 + b * 0.114 > 128;
}
+15 -2
View File
@@ -2,6 +2,7 @@ import type { CTAQuestion } from "../../../types/questions";
import { h } from "preact";
import Headline from "./Headline";
import HtmlBody from "./HtmlBody";
import SubmitButton from "./SubmitButton";
interface CTAQuestionProps {
question: CTAQuestion;
@@ -28,7 +29,7 @@ export default function CTAQuestion({ question, onSubmit, lastQuestion, brandCol
{question.dismissButtonLabel || "Skip"}
</button>
)}
<button
{/* <button
type="button"
onClick={() => {
if (question.buttonExternal && question.buttonUrl) {
@@ -39,7 +40,19 @@ export default function CTAQuestion({ question, onSubmit, lastQuestion, brandCol
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm fb-hover:opacity-90 fb-focus:outline-none fb-focus:ring-2 fb-focus:ring-slate-500 fb-focus:ring-offset-2"
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
</button> */}
<SubmitButton
question={question}
lastQuestion={lastQuestion}
brandColor={brandColor}
onClick={() => {
if (question.buttonExternal && question.buttonUrl) {
window?.open(question.buttonUrl, "_blank")?.focus();
}
onSubmit({ [question.id]: "clicked" });
}}
type="button"
/>
</div>
</div>
);
@@ -4,6 +4,7 @@ import { useState } from "preact/hooks";
import { cn } from "../lib/utils";
import Headline from "./Headline";
import Subheader from "./Subheader";
import SubmitButton from "./SubmitButton";
interface MultipleChoiceMultiProps {
question: MultipleChoiceMultiQuestion;
@@ -90,12 +91,12 @@ export default function MultipleChoiceMultiQuestion({
/>
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-between">
<div></div>
<button
type="submit"
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-offset-2 focus:fb-ring-slate-500"
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
<SubmitButton
question={question}
lastQuestion={lastQuestion}
brandColor={brandColor}
onClick={() => {}}
/>
</div>
</form>
);
@@ -4,6 +4,7 @@ import { cn } from "../lib/utils";
import type { MultipleChoiceSingleQuestion } from "../../../types/questions";
import Headline from "./Headline";
import Subheader from "./Subheader";
import SubmitButton from "./SubmitButton";
interface MultipleChoiceSingleProps {
question: MultipleChoiceSingleQuestion;
@@ -71,12 +72,12 @@ export default function MultipleChoiceSingleQuestion({
</div>
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-between">
<div></div>
<button
type="submit"
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-offset-2 focus:ring-slate-500"
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
<SubmitButton
question={question}
lastQuestion={lastQuestion}
brandColor={brandColor}
onClick={() => {}}
/>
</div>
</form>
);
+7 -6
View File
@@ -4,6 +4,7 @@ import { cn } from "../lib/utils";
import type { NPSQuestion } from "../../../types/questions";
import Headline from "./Headline";
import Subheader from "./Subheader";
import SubmitButton from "./SubmitButton";
interface NPSQuestionProps {
question: NPSQuestion;
@@ -70,12 +71,12 @@ export default function NPSQuestion({ question, onSubmit, lastQuestion, brandCol
{!question.required && (
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-between">
<div></div>
<button
type="submit"
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-offset-2 focus:fb-ring-slate-500"
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
<SubmitButton
question={question}
lastQuestion={lastQuestion}
brandColor={brandColor}
onClick={() => {}}
/>
</div>
)}
</form>
@@ -2,6 +2,7 @@ import type { OpenTextQuestion } from "../../../types/questions";
import { h } from "preact";
import Headline from "./Headline";
import Subheader from "./Subheader";
import SubmitButton from "./SubmitButton";
interface OpenTextQuestionProps {
question: OpenTextQuestion;
@@ -40,12 +41,12 @@ export default function OpenTextQuestion({
</div>
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-between">
<div></div>
<button
type="submit"
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-offset-2 focus:fb-ring-slate-500"
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
<SubmitButton
question={question}
lastQuestion={lastQuestion}
brandColor={brandColor}
onClick={() => {}}
/>
</div>
</form>
);
@@ -16,6 +16,7 @@ import {
TiredFace,
WearyFace,
} from "./Smileys";
import SubmitButton from "./SubmitButton";
interface RatingQuestionProps {
question: RatingQuestion;
@@ -149,12 +150,12 @@ export default function RatingQuestion({
{!question.required && (
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-between">
<div></div>
<button
type="submit"
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-slate-500 focus:fb-ring-offset-2"
style={{ backgroundColor: brandColor }}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
<SubmitButton
question={question}
lastQuestion={lastQuestion}
brandColor={brandColor}
onClick={() => {}}
/>
</div>
)}
</form>
@@ -0,0 +1,20 @@
import { h } from "preact";
import { cn } from "@/../../packages/lib/cn";
import { isLight } from "../lib/utils";
function SubmitButton({ question, lastQuestion, brandColor, onClick, type = "submit" }) {
return (
<button
type={type}
className={cn(
"fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-slate-500 focus:fb-ring-offset-2",
isLight(brandColor) ? "fb-text-black" : "fb-text-white"
)}
style={{ backgroundColor: brandColor }}
onClick={onClick}>
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
</button>
);
}
export default SubmitButton;
+14
View File
@@ -1,3 +1,17 @@
export const cn = (...classes) => {
return classes.filter(Boolean).join(" ");
};
export function isLight(color) {
let r, g, b;
if (color.length === 4) {
r = parseInt(color[1] + color[1], 16);
g = parseInt(color[2] + color[2], 16);
b = parseInt(color[3] + color[3], 16);
} else if (color.length === 7) {
r = parseInt(color[1] + color[2], 16);
g = parseInt(color[3] + color[4], 16);
b = parseInt(color[5] + color[6], 16);
}
return r * 0.299 + g * 0.587 + b * 0.114 > 128;
}