Compare commits

...

28 Commits

Author SHA1 Message Date
Piyush Gupta
d63beb7ee2 Merge branch 'feature/docs-in-page-section-nav' of https://github.com/bitroy/formbricks into bitroy-docs 2024-06-14 10:17:25 +05:30
Pranoy Roy
90f6e0f1ed Merge branch 'formbricks:main' into feature/docs-in-page-section-nav 2024-06-13 18:37:02 +05:30
Piyush Gupta
4e6ab1c2bb feat: adds product config (#2760)
Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
2024-06-13 12:51:02 +00:00
Johannes
d8e71a42c0 side nav styling consistency 2024-06-13 13:50:04 +02:00
Dhruwang Jariwala
543d85eb28 feat: Hidden fields and metadata for integrations (#2752)
Co-authored-by: Johannes <72809645+jobenjada@users.noreply.github.com>
2024-06-13 11:14:43 +00:00
Matti Nannt
afe01a61ae fix: remove unused telemetry to fix build errors (#2761) 2024-06-13 08:42:14 +02:00
Pranoy Roy
d124fdd742 Merge branch 'formbricks:main' into feature/docs-in-page-section-nav 2024-06-12 23:19:45 +05:30
bitroy
d1bacd6c0e feat: highlight side nav items on scroll 2024-06-12 23:18:41 +05:30
Johannes
b4c86835ed fix: survey padding and add report survey (#2763) 2024-06-12 15:58:19 +00:00
Johannes
e6f9a53c34 Merge branch 'main' into feature/docs-in-page-section-nav 2024-06-12 16:34:24 +02:00
Dhruwang Jariwala
ab80bc1bf2 feat: language switch (#2692)
Co-authored-by: Johannes <johannes@formbricks.com>
Co-authored-by: Matti Nannt <mail@matthiasnannt.com>
2024-06-12 14:10:22 +00:00
Matti Nannt
5e5a9fac00 chore: rename responses to completed in stats card (#2759) 2024-06-12 15:20:59 +02:00
Dhruwang Jariwala
09b6805886 fix: recall from hidden fields (#2758) 2024-06-12 11:26:17 +00:00
Matti Nannt
33822350fd fix: add missing dependency in ee package (#2757) 2024-06-11 21:41:45 +02:00
bitroy
e8fd9106e5 feat: updated docs layout wrt side navigation 2024-06-11 22:49:53 +05:30
Pranoy Roy
b2b6d09a9e Merge branch 'formbricks:main' into feature/docs-in-page-section-nav 2024-06-11 22:15:39 +05:30
Pranoy Roy
8697c587a7 Merge branch 'formbricks:main' into feature/docs-in-page-section-nav 2024-06-07 13:19:53 +05:30
bitroy
8c7769a40a feat: updated in-page side nav active link style 2024-06-06 09:48:36 +05:30
bitroy
821cbbdb07 feat: enhanced in-page side navigation for docs with nested content and url navigation 2024-06-05 21:42:15 +05:30
Pranoy Roy
9618e7dae7 Merge branch 'formbricks:main' into feature/docs-in-page-section-nav 2024-06-05 21:34:55 +05:30
Pranoy Roy
da103f840b Merge branch 'formbricks:main' into feature/docs-in-page-section-nav 2024-06-05 15:11:31 +05:30
Piyush Gupta
24873734e9 Merge branch 'main' of https://github.com/formbricks/formbricks into bitroy-docs 2024-06-05 13:37:52 +05:30
Pranoy Roy
207342dc4a Merge branch 'formbricks:main' into feature/docs-in-page-section-nav 2024-06-03 21:09:50 +05:30
Pranoy Roy
f1fdc78739 Merge branch 'formbricks:main' into feature/docs-in-page-section-nav 2024-06-03 20:59:44 +05:30
bitroy
f601ad062e feat: updated docs section nav styles 2024-06-03 11:06:03 +05:30
bitroy
da202cd3d2 feat: updated docs side nav style 2024-06-03 09:52:02 +05:30
bitroy
244d04f78d feat: added in-page section navigation 2024-06-03 00:17:46 +05:30
bitroy
51e79165bd feat: added a simple in-page side navigation for docs 2024-06-02 21:13:33 +05:30
628 changed files with 1625 additions and 3118 deletions

View File

@@ -9,7 +9,6 @@ import {
ShieldCheckIcon,
UsersIcon,
} from "lucide-react";
import { classNames } from "../lib/utils";
const navigation = [

View File

@@ -1,6 +1,5 @@
import type { AppProps } from "next/app";
import Head from "next/head";
import "../styles/globals.css";
const App = ({ Component, pageProps }: AppProps) => {

View File

@@ -1,9 +1,7 @@
import Image from "next/image";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import formbricks from "@formbricks/js/app";
import { SurveySwitch } from "../../components/SurveySwitch";
import fbsetup from "../../public/fb-setup.png";

View File

@@ -1,9 +1,7 @@
import Image from "next/image";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import formbricks from "@formbricks/js/website";
import { SurveySwitch } from "../../components/SurveySwitch";
import fbsetup from "../../public/fb-setup.png";
@@ -36,7 +34,7 @@ const AppPage = ({}) => {
if (process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID && process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST) {
const defaultAttributes = {
language: "de",
language: "en",
};
formbricks.init({

View File

@@ -1,5 +1,4 @@
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@formbricks/ui/Accordion";
import { FaqJsonLdComponent } from "./FAQPageJsonLd";
const FAQ_DATA = [

View File

@@ -3,7 +3,6 @@
import { navigation } from "@/lib/navigation";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { Button } from "./Button";
import { DiscordIcon } from "./icons/DiscordIcon";
import { GithubIcon } from "./icons/GithubIcon";
@@ -116,7 +115,7 @@ const SmallPrint = () => {
export const Footer = () => {
return (
<footer className="mx-auto w-full max-w-2xl space-y-10 pb-16 lg:max-w-5xl">
<footer className="mb-10 mt-10 flex-auto pb-16">
<PageNavigation />
<SmallPrint />
</footer>

View File

@@ -6,7 +6,6 @@ import clsx from "clsx";
import { motion, useScroll, useTransform } from "framer-motion";
import Link from "next/link";
import { forwardRef } from "react";
import { Button } from "./Button";
import { MobileNavigation, useIsInsideMobileNavigation, useMobileNavigationStore } from "./MobileNavigation";
import { ThemeToggle } from "./ThemeToggle";

View File

@@ -44,7 +44,7 @@ const Anchor = ({ id, inView, children }: { id: string; inView: boolean; childre
);
};
export const Heading = <Level extends 2 | 3>({
export const Heading = <Level extends 2 | 3 | 4>({
children,
tag,
label,
@@ -59,11 +59,11 @@ export const Heading = <Level extends 2 | 3>({
anchor?: boolean;
}) => {
level = level ?? (2 as Level);
let Component = `h${level}` as "h2" | "h3";
let ref = useRef<HTMLHeadingElement>(null);
let registerHeading = useSectionStore((s) => s.registerHeading);
const Component: "h2" | "h3" | "h4" = `h${level}`;
const ref = useRef<HTMLHeadingElement>(null);
const registerHeading = useSectionStore((s) => s.registerHeading);
let inView = useInView(ref, {
const inView = useInView(ref, {
margin: `${remToPx(-3.5)}px 0px 0px 0px`,
amount: "all",
});
@@ -71,8 +71,12 @@ export const Heading = <Level extends 2 | 3>({
useEffect(() => {
if (level === 2) {
registerHeading({ id: props.id, ref, offsetRem: tag || label ? 8 : 6 });
} else if (level === 3) {
registerHeading({ id: props.id, ref, offsetRem: tag || label ? 7 : 5 });
} else if (level === 4) {
registerHeading({ id: props.id, ref, offsetRem: tag || label ? 6 : 4 });
}
});
}, [label, level, props.id, registerHeading, tag]);
return (
<>

View File

@@ -2,10 +2,10 @@
import { Logo } from "@/components/Logo";
import { Navigation } from "@/components/Navigation";
import SideNavigation from "@/components/SideNavigation";
import { motion } from "framer-motion";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { Footer } from "./Footer";
import { Header } from "./Header";
import { type Section, SectionProvider } from "./SectionProvider";
@@ -17,7 +17,7 @@ export const Layout = ({
children: React.ReactNode;
allSections: Record<string, Array<Section>>;
}) => {
let pathname = usePathname();
const pathname = usePathname();
return (
<SectionProvider sections={allSections[pathname || ""] ?? []}>
@@ -35,9 +35,12 @@ export const Layout = ({
<Navigation className="hidden lg:mt-10 lg:block" isMobile={false} />
</div>
</motion.header>
<div className="relative flex h-full flex-col px-4 pt-14 sm:px-6 lg:px-8">
<main className="flex-auto">{children}</main>
<Footer />
<div className="flex h-screen flex-col">
<div className="flex flex-col px-4 pt-14 sm:px-6 lg:w-[calc(100%-20rem)] lg:px-8">
<main className="overflow-y-auto overflow-x-hidden">{children}</main>
<Footer />
</div>
<SideNavigation pathname={pathname} />
</div>
</div>
</SectionProvider>

View File

@@ -8,7 +8,6 @@ import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useRef, useState } from "react";
import { Button } from "./Button";
import { useIsInsideMobileNavigation } from "./MobileNavigation";
import { useSectionStore } from "./SectionProvider";

View File

@@ -0,0 +1,80 @@
import useTableContentObserver from "@/hooks/useTableContentObserver";
import Link from "next/link";
import { useEffect, useState } from "react";
type Heading = {
id: string;
text: string | null;
level: number;
};
const SideNavigation = ({ pathname }) => {
const [headings, setHeadings] = useState<Heading[]>([]);
const [selectedId, setSelectedId] = useState<string | null>(null);
useTableContentObserver(setSelectedId, pathname);
useEffect(() => {
const getHeadings = () => {
const headingElements = document.querySelectorAll("h2[id], h3[id], h4[id]");
const headings: Heading[] = Array.from(headingElements).map((heading) => ({
id: heading.id,
text: heading.textContent,
level: parseInt(heading.tagName.slice(1)),
}));
const hasH2 = headings.some((heading) => heading.level === 2);
setHeadings(hasH2 ? headings : []);
};
getHeadings();
}, [pathname]);
const renderHeading = (items: Heading[], currentLevel: number) => (
<ul className="ml-1 mt-4">
{items.map((heading, index) => {
if (heading.level === currentLevel) {
let nextIndex = index + 1;
while (nextIndex < items.length && items[nextIndex].level > currentLevel) {
nextIndex++;
}
return (
<li
key={heading.text}
className={`mb-4 ml-4 text-slate-900 dark:text-white ml-${heading.level === 2 ? 0 : heading.level === 3 ? 4 : 6}`}>
<Link
href={`#${heading.id}`}
onClick={() => setSelectedId(heading.id)}
className={`${
heading.id === selectedId
? "text-brand font-medium"
: "font-normal text-slate-600 hover:text-slate-950 dark:text-white dark:hover:text-slate-50"
}`}>
{heading.text}
</Link>
{nextIndex > index + 1 && renderHeading(items.slice(index + 1, nextIndex), currentLevel + 1)}
</li>
);
}
return null;
})}
</ul>
);
if (headings.length) {
return (
<aside className="fixed right-0 top-0 hidden h-[calc(100%-2.5rem)] w-80 overflow-hidden overflow-y-auto pr-8 pt-16 text-sm [scrollbar-width:none] lg:mt-10 lg:block">
<div className="border-l border-slate-200 dark:border-slate-700">
<h3 className="ml-5 mt-1 text-xs font-semibold uppercase text-slate-400">on this page</h3>
{renderHeading(headings, 2)}
</div>
</aside>
);
}
return null;
};
export default SideNavigation;

View File

@@ -19,10 +19,19 @@ export const wrapper = ({ children }: { children: React.ReactNode }) => {
);
};
export const h2 = (props: Omit<React.ComponentPropsWithoutRef<typeof Heading>, "level">) => {
return <Heading level={2} {...props} />;
const createHeadingComponent = (level: 2 | 3 | 4) => {
const Component = (props: Omit<React.ComponentPropsWithoutRef<typeof Heading>, "level">) => {
return <Heading level={level} {...props} />;
};
Component.displayName = `H${level}`;
return Component;
};
export const h2 = createHeadingComponent(2);
export const h3 = createHeadingComponent(3);
export const h4 = createHeadingComponent(4);
const InfoIcon = (props: React.ComponentPropsWithoutRef<"svg">) => {
return (
<svg viewBox="0 0 16 16" aria-hidden="true" {...props}>

View File

@@ -0,0 +1,44 @@
import { useEffect, useRef } from "react";
const useTableContentObserver = (setActiveId, pathname) => {
const headingElementsRef = useRef({});
useEffect(() => {
const callback = (headings) => {
headingElementsRef.current = headings.reduce((map, headingElement) => {
return { ...map, [headingElement.target.id]: headingElement };
}, {});
const visibleHeadings = [];
Object.keys(headingElementsRef.current).forEach((key) => {
const headingElement = headingElementsRef.current[key];
if (headingElement.isIntersecting) visibleHeadings.push(headingElement);
});
const getIndexFromId = (id) => headingElements.findIndex((heading) => heading.id === id);
if (visibleHeadings.length === 1) {
setActiveId(visibleHeadings[0].target.id);
} else if (visibleHeadings.length > 1) {
const sortedVisibleHeadings = visibleHeadings.sort(
(a, b) => getIndexFromId(a.target.id) > getIndexFromId(b.target.id)
);
setActiveId(sortedVisibleHeadings[0].target.id);
}
};
const observer = new IntersectionObserver(callback, {
rootMargin: "-40px 0px -40% 0px",
});
const headingElements = Array.from(document.querySelectorAll("h2[id], h3[id], h4[id]"));
headingElements.forEach((element) => observer.observe(element));
return () => {
observer.disconnect();
headingElementsRef.current = {};
};
}, [setActiveId, pathname]);
};
export default useTableContentObserver;

View File

@@ -46,9 +46,9 @@ const rehypeShiki = () => {
const rehypeSlugify = () => {
return (tree) => {
let slugify = slugifyWithCounter();
const slugify = slugifyWithCounter();
visit(tree, "element", (node) => {
if (node.tagName === "h2" && !node.properties.id) {
if (["h2", "h3", "h4"].includes(node.tagName) && !node.properties.id) {
node.properties.id = slugify(toString(node));
}
});
@@ -83,15 +83,15 @@ const rehypeAddMDXExports = (getExports) => {
};
const getSections = (node) => {
let sections = [];
const sections = [];
for (let child of node.children ?? []) {
if (child.type === "element" && child.tagName === "h2") {
for (const child of node.children ?? []) {
if (child.type === "element" && ["h2", "h3", "h4"].includes(child.tagName)) {
sections.push(`{
title: ${JSON.stringify(toString(child))},
id: ${JSON.stringify(child.properties.id)},
...${child.properties.annotation}
}`);
title: ${JSON.stringify(toString(child))},
id: ${JSON.stringify(child.properties.id)},
...${child.properties.annotation}
}`);
} else if (child.children) {
sections.push(...getSections(child));
}

View File

@@ -3,7 +3,6 @@ import forms from "@tailwindcss/forms";
import typographyPlugin from "@tailwindcss/typography";
import { type Config } from "tailwindcss";
import defaultTheme from "tailwindcss/defaultTheme";
import typographyStyles from "./typography";
export default {

View File

@@ -1,5 +1,4 @@
import type { Preview } from "@storybook/react";
import "../../web/app/globals.css";
const preview: Preview = {

View File

@@ -1,5 +1,4 @@
import { useState } from "react";
import "./App.css";
export const App = () => {

View File

@@ -1,6 +1,5 @@
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import "./index.css";

View File

@@ -3,7 +3,6 @@ import { PosthogIdentify } from "@/app/(app)/environments/[environmentId]/compon
import { ResponseFilterProvider } from "@/app/(app)/environments/[environmentId]/components/ResponseFilterContext";
import { getServerSession } from "next-auth";
import { redirect } from "next/navigation";
import { authOptions } from "@formbricks/lib/authOptions";
import { hasUserEnvironmentAccess } from "@formbricks/lib/environment/auth";
import { getEnvironment } from "@formbricks/lib/environment/service";

View File

@@ -5,7 +5,6 @@ import { createId } from "@paralleldrive/cuid2";
import * as Collapsible from "@radix-ui/react-collapsible";
import { PlusIcon } from "lucide-react";
import { useState } from "react";
import { cn } from "@formbricks/lib/cn";
import { TProduct } from "@formbricks/types/product";

View File

@@ -1,8 +1,6 @@
"use client";
import { PlusIcon, TrashIcon } from "lucide-react";
import { useState } from "react";
import { PlusIcon } from "lucide-react";
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TSurvey, TSurveyAddressQuestion } from "@formbricks/types/surveys";
@@ -32,7 +30,6 @@ export const AddressQuestionForm = ({
setSelectedLanguageCode,
attributeClasses,
}: AddressQuestionFormProps): JSX.Element => {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const surveyLanguageCodes = extractLanguageCodes(localSurvey.languages ?? []);
return (
@@ -51,7 +48,7 @@ export const AddressQuestionForm = ({
/>
<div>
{showSubheader && (
{question.subheader !== undefined && (
<div className="inline-flex w-full items-center">
<div className="w-full">
<QuestionFormInput
@@ -67,17 +64,9 @@ export const AddressQuestionForm = ({
attributeClasses={attributeClasses}
/>
</div>
<TrashIcon
className="ml-2 mt-10 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: undefined });
}}
/>
</div>
)}
{!showSubheader && (
{question.subheader === undefined && (
<Button
size="sm"
variant="minimal"
@@ -87,7 +76,6 @@ export const AddressQuestionForm = ({
updateQuestion(questionIdx, {
subheader: createI18nString("", surveyLanguageCodes),
});
setShowSubheader(true);
}}>
<PlusIcon className="mr-1 h-4 w-4" />
Add Description

View File

@@ -1,6 +1,5 @@
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TSurvey, TSurveyQuestion } from "@formbricks/types/surveys";
import { LogicEditor } from "./LogicEditor";
import { UpdateQuestionId } from "./UpdateQuestionId";

View File

@@ -3,14 +3,12 @@
import * as Collapsible from "@radix-ui/react-collapsible";
import { CheckIcon } from "lucide-react";
import { UseFormReturn } from "react-hook-form";
import { cn } from "@formbricks/lib/cn";
import { TProductStyling } from "@formbricks/types/product";
import { TSurveyStyling } from "@formbricks/types/surveys";
import { Badge } from "@formbricks/ui/Badge";
import { FormControl, FormDescription, FormField, FormItem, FormLabel } from "@formbricks/ui/Form";
import { Slider } from "@formbricks/ui/Slider";
import { SurveyBgSelectorTab } from "./SurveyBgSelectorTab";
interface BackgroundStylingCardProps {

View File

@@ -1,6 +1,4 @@
import { PlusIcon, TrashIcon } from "lucide-react";
import { useState } from "react";
import { PlusIcon } from "lucide-react";
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TSurvey, TSurveyCalQuestion } from "@formbricks/types/surveys";
@@ -31,7 +29,6 @@ export const CalQuestionForm = ({
isInvalid,
attributeClasses,
}: CalQuestionFormProps): JSX.Element => {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const surveyLanguageCodes = extractLanguageCodes(localSurvey.languages);
return (
@@ -49,7 +46,7 @@ export const CalQuestionForm = ({
attributeClasses={attributeClasses}
/>
<div>
{showSubheader && (
{question.subheader !== undefined && (
<div className="inline-flex w-full items-center">
<div className="w-full">
<QuestionFormInput
@@ -65,17 +62,9 @@ export const CalQuestionForm = ({
attributeClasses={attributeClasses}
/>
</div>
<TrashIcon
className="ml-2 mt-10 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: undefined });
}}
/>
</div>
)}
{!showSubheader && (
{question.subheader === undefined && (
<Button
size="sm"
className="mt-3"
@@ -85,7 +74,6 @@ export const CalQuestionForm = ({
updateQuestion(questionIdx, {
subheader: createI18nString("", surveyLanguageCodes),
});
setShowSubheader(true);
}}>
{" "}
<PlusIcon className="mr-1 h-4 w-4" />

View File

@@ -1,5 +1,4 @@
import { useState } from "react";
import { ColorPicker } from "@formbricks/ui/ColorPicker";
interface ColorSurveyBgProps {

View File

@@ -1,6 +1,4 @@
import { PlusIcon, TrashIcon } from "lucide-react";
import { useState } from "react";
import { PlusIcon } from "lucide-react";
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TSurvey, TSurveyDateQuestion } from "@formbricks/types/surveys";
@@ -46,7 +44,6 @@ export const DateQuestionForm = ({
setSelectedLanguageCode,
attributeClasses,
}: IDateQuestionFormProps): JSX.Element => {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const surveyLanguageCodes = extractLanguageCodes(localSurvey.languages);
return (
@@ -64,7 +61,7 @@ export const DateQuestionForm = ({
attributeClasses={attributeClasses}
/>
<div>
{showSubheader && (
{question.subheader !== undefined && (
<div className="mt-2 inline-flex w-full items-center">
<div className="w-full">
<QuestionFormInput
@@ -80,18 +77,10 @@ export const DateQuestionForm = ({
attributeClasses={attributeClasses}
/>
</div>
<TrashIcon
className="ml-2 mt-10 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: undefined });
}}
/>
</div>
)}
{!showSubheader && (
{question.subheader === undefined && (
<Button
size="sm"
className="mt-3"
@@ -101,9 +90,7 @@ export const DateQuestionForm = ({
updateQuestion(questionIdx, {
subheader: createI18nString("", surveyLanguageCodes),
});
setShowSubheader(true);
}}>
{" "}
<PlusIcon className="mr-1 h-4 w-4" />
Add Description
</Button>

View File

@@ -2,7 +2,6 @@
import * as Collapsible from "@radix-ui/react-collapsible";
import { useState } from "react";
import { cn } from "@formbricks/lib/cn";
import { getLocalizedValue } from "@formbricks/lib/i18n/utils";
import { TAttributeClass } from "@formbricks/types/attributeClasses";

View File

@@ -1,9 +1,8 @@
"use client";
import { PlusIcon, TrashIcon, XCircleIcon } from "lucide-react";
import { PlusIcon, XCircleIcon } from "lucide-react";
import { useMemo, useState } from "react";
import { toast } from "react-hot-toast";
import { extractLanguageCodes } from "@formbricks/lib/i18n/utils";
import { createI18nString } from "@formbricks/lib/i18n/utils";
import { useGetBillingInfo } from "@formbricks/lib/organization/hooks/useGetBillingInfo";
@@ -40,7 +39,6 @@ export const FileUploadQuestionForm = ({
setSelectedLanguageCode,
attributeClasses,
}: FileUploadFormProps): JSX.Element => {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const [extension, setExtension] = useState("");
const {
billingInfo,
@@ -128,7 +126,7 @@ export const FileUploadQuestionForm = ({
attributeClasses={attributeClasses}
/>
<div>
{showSubheader && (
{question.subheader !== undefined && (
<div className="inline-flex w-full items-center">
<div className="w-full">
<QuestionFormInput
@@ -144,17 +142,9 @@ export const FileUploadQuestionForm = ({
attributeClasses={attributeClasses}
/>
</div>
<TrashIcon
className="ml-2 mt-10 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: undefined });
}}
/>
</div>
)}
{!showSubheader && (
{question.subheader === undefined && (
<Button
size="sm"
className="mt-3"
@@ -164,9 +154,7 @@ export const FileUploadQuestionForm = ({
updateQuestion(questionIdx, {
subheader: createI18nString("", surveyLanguageCodes),
});
setShowSubheader(true);
}}>
{" "}
<PlusIcon className="mr-1 h-4 w-4" />
Add Description
</Button>

View File

@@ -3,7 +3,6 @@
import * as Collapsible from "@radix-ui/react-collapsible";
import { useState } from "react";
import { toast } from "react-hot-toast";
import { cn } from "@formbricks/lib/cn";
import { TSurvey, TSurveyHiddenFields } from "@formbricks/types/surveys";
import { Button } from "@formbricks/ui/Button";
@@ -11,7 +10,6 @@ import { Input } from "@formbricks/ui/Input";
import { Label } from "@formbricks/ui/Label";
import { Switch } from "@formbricks/ui/Switch";
import { Tag } from "@formbricks/ui/Tag";
import { validateId } from "../lib/validation";
interface HiddenFieldsCardProps {

View File

@@ -4,7 +4,6 @@ import * as Collapsible from "@radix-ui/react-collapsible";
import { AlertCircleIcon, CheckIcon, EarthIcon, LinkIcon, MonitorIcon, SmartphoneIcon } from "lucide-react";
import Link from "next/link";
import { useEffect, useState } from "react";
import { cn } from "@formbricks/lib/cn";
import { TEnvironment } from "@formbricks/types/environment";
import { TSegment } from "@formbricks/types/segment";

View File

@@ -1,16 +1,13 @@
"use client";
import { PlusIcon, TrashIcon } from "lucide-react";
import { useState } from "react";
import { toast } from "react-hot-toast";
import { createI18nString, extractLanguageCodes, getLocalizedValue } from "@formbricks/lib/i18n/utils";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TI18nString, TSurvey, TSurveyMatrixQuestion } from "@formbricks/types/surveys";
import { Button } from "@formbricks/ui/Button";
import { Label } from "@formbricks/ui/Label";
import { QuestionFormInput } from "@formbricks/ui/QuestionFormInput";
import { isLabelValidForAllLanguages } from "../lib/validation";
interface MatrixQuestionFormProps {
@@ -35,7 +32,6 @@ export const MatrixQuestionForm = ({
setSelectedLanguageCode,
attributeClasses,
}: MatrixQuestionFormProps): JSX.Element => {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const languageCodes = extractLanguageCodes(localSurvey.languages);
// Function to add a new Label input field
const handleAddLabel = (type: "row" | "column") => {
@@ -117,7 +113,7 @@ export const MatrixQuestionForm = ({
attributeClasses={attributeClasses}
/>
<div>
{showSubheader && (
{question.subheader !== undefined && (
<div className="inline-flex w-full items-center">
<div className="w-full">
<QuestionFormInput
@@ -133,23 +129,19 @@ export const MatrixQuestionForm = ({
attributeClasses={attributeClasses}
/>
</div>
<TrashIcon
className="ml-2 mt-10 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: undefined });
}}
/>
</div>
)}
{!showSubheader && (
{question.subheader === undefined && (
<Button
size="sm"
variant="minimal"
className="mt-3"
type="button"
onClick={() => setShowSubheader(true)}>
onClick={() => {
updateQuestion(questionIdx, {
subheader: createI18nString("", languageCodes),
});
}}>
<PlusIcon className="mr-1 h-4 w-4" />
Add Description
</Button>

View File

@@ -3,7 +3,7 @@
import { DndContext } from "@dnd-kit/core";
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
import { createId } from "@paralleldrive/cuid2";
import { PlusIcon, TrashIcon } from "lucide-react";
import { PlusIcon } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
import { getLocalizedValue } from "@formbricks/lib/i18n/utils";
@@ -45,7 +45,6 @@ export const MultipleChoiceQuestionForm = ({
}: OpenQuestionFormProps): JSX.Element => {
const lastChoiceRef = useRef<HTMLInputElement>(null);
const [isNew, setIsNew] = useState(true);
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const [isInvalidValue, setisInvalidValue] = useState<string | null>(null);
const questionRef = useRef<HTMLInputElement>(null);
@@ -196,7 +195,7 @@ export const MultipleChoiceQuestionForm = ({
/>
<div>
{showSubheader && (
{question.subheader !== undefined && (
<div className="inline-flex w-full items-center">
<div className="w-full">
<QuestionFormInput
@@ -212,17 +211,9 @@ export const MultipleChoiceQuestionForm = ({
attributeClasses={attributeClasses}
/>
</div>
<TrashIcon
className="ml-2 mt-10 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: undefined });
}}
/>
</div>
)}
{!showSubheader && (
{question.subheader === undefined && (
<Button
size="sm"
variant="minimal"
@@ -232,9 +223,7 @@ export const MultipleChoiceQuestionForm = ({
updateQuestion(questionIdx, {
subheader: createI18nString("", surveyLanguageCodes),
});
setShowSubheader(true);
}}>
{" "}
<PlusIcon className="mr-1 h-4 w-4" />
Add Description
</Button>

View File

@@ -1,8 +1,6 @@
"use client";
import { PlusIcon, TrashIcon } from "lucide-react";
import { useState } from "react";
import { PlusIcon } from "lucide-react";
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TSurvey, TSurveyNPSQuestion } from "@formbricks/types/surveys";
@@ -32,7 +30,6 @@ export const NPSQuestionForm = ({
setSelectedLanguageCode,
attributeClasses,
}: NPSQuestionFormProps): JSX.Element => {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const surveyLanguageCodes = extractLanguageCodes(localSurvey.languages);
return (
<form>
@@ -50,7 +47,7 @@ export const NPSQuestionForm = ({
/>
<div>
{showSubheader && (
{question.subheader !== undefined && (
<div className="mt-2 inline-flex w-full items-center">
<div className="w-full">
<QuestionFormInput
@@ -66,17 +63,9 @@ export const NPSQuestionForm = ({
attributeClasses={attributeClasses}
/>
</div>
<TrashIcon
className="ml-2 mt-10 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: undefined });
}}
/>
</div>
)}
{!showSubheader && (
{question.subheader === undefined && (
<Button
size="sm"
variant="minimal"
@@ -86,7 +75,6 @@ export const NPSQuestionForm = ({
updateQuestion(questionIdx, {
subheader: createI18nString("", surveyLanguageCodes),
});
setShowSubheader(true);
}}>
{" "}
<PlusIcon className="mr-1 h-4 w-4" />

View File

@@ -1,16 +1,6 @@
"use client";
import {
HashIcon,
LinkIcon,
MailIcon,
MessageSquareTextIcon,
PhoneIcon,
PlusIcon,
TrashIcon,
} from "lucide-react";
import { useState } from "react";
import { HashIcon, LinkIcon, MailIcon, MessageSquareTextIcon, PhoneIcon, PlusIcon } from "lucide-react";
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import {
@@ -53,7 +43,6 @@ export const OpenQuestionForm = ({
setSelectedLanguageCode,
attributeClasses,
}: OpenQuestionFormProps): JSX.Element => {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const defaultPlaceholder = getPlaceholderByInputType(question.inputType ?? "text");
const surveyLanguageCodes = extractLanguageCodes(localSurvey.languages ?? []);
const handleInputChange = (inputType: TSurveyOpenTextQuestionInputType) => {
@@ -81,7 +70,7 @@ export const OpenQuestionForm = ({
/>
<div>
{showSubheader && (
{question.subheader !== undefined && (
<div className="inline-flex w-full items-center">
<div className="w-full">
<QuestionFormInput
@@ -97,17 +86,9 @@ export const OpenQuestionForm = ({
label={"Description"}
/>
</div>
<TrashIcon
className="ml-2 mt-10 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: undefined });
}}
/>
</div>
)}
{!showSubheader && (
{question.subheader === undefined && (
<Button
size="sm"
variant="minimal"
@@ -117,7 +98,6 @@ export const OpenQuestionForm = ({
updateQuestion(questionIdx, {
subheader: createI18nString("", surveyLanguageCodes),
});
setShowSubheader(true);
}}>
<PlusIcon className="mr-1 h-4 w-4" />
Add Description

View File

@@ -1,7 +1,5 @@
import { createId } from "@paralleldrive/cuid2";
import { PlusIcon, TrashIcon } from "lucide-react";
import { useState } from "react";
import { PlusIcon } from "lucide-react";
import { cn } from "@formbricks/lib/cn";
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
@@ -34,7 +32,6 @@ export const PictureSelectionForm = ({
isInvalid,
attributeClasses,
}: PictureSelectionFormProps): JSX.Element => {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const environmentId = localSurvey.environmentId;
const surveyLanguageCodes = extractLanguageCodes(localSurvey.languages);
@@ -53,7 +50,7 @@ export const PictureSelectionForm = ({
attributeClasses={attributeClasses}
/>
<div>
{showSubheader && (
{question.subheader !== undefined && (
<div className="mt-2 inline-flex w-full items-center">
<div className="w-full">
<QuestionFormInput
@@ -69,17 +66,9 @@ export const PictureSelectionForm = ({
attributeClasses={attributeClasses}
/>
</div>
<TrashIcon
className="ml-2 mt-10 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: undefined });
}}
/>
</div>
)}
{!showSubheader && (
{question.subheader === undefined && (
<Button
size="sm"
variant="minimal"
@@ -89,9 +78,7 @@ export const PictureSelectionForm = ({
updateQuestion(questionIdx, {
subheader: createI18nString("", surveyLanguageCodes),
});
setShowSubheader(true);
}}>
{" "}
<PlusIcon className="mr-1 h-4 w-4" />
Add Description
</Button>

View File

@@ -1,9 +1,7 @@
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TProduct } from "@formbricks/types/product";
import { TSurvey } from "@formbricks/types/surveys";
import { QuestionCard } from "./QuestionCard";
interface QuestionsDraggableProps {

View File

@@ -1,6 +1,5 @@
import { PaintbrushIcon, Rows3Icon, SettingsIcon } from "lucide-react";
import { useMemo } from "react";
import { cn } from "@formbricks/lib/cn";
import { TSurveyEditorTabs } from "@formbricks/types/surveys";

View File

@@ -1,13 +1,10 @@
import { HashIcon, PlusIcon, SmileIcon, StarIcon, TrashIcon } from "lucide-react";
import { useState } from "react";
import { HashIcon, PlusIcon, SmileIcon, StarIcon } from "lucide-react";
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TSurvey, TSurveyRatingQuestion } from "@formbricks/types/surveys";
import { Button } from "@formbricks/ui/Button";
import { Label } from "@formbricks/ui/Label";
import { QuestionFormInput } from "@formbricks/ui/QuestionFormInput";
import { Dropdown } from "./RatingTypeDropdown";
interface RatingQuestionFormProps {
@@ -32,7 +29,6 @@ export const RatingQuestionForm = ({
setSelectedLanguageCode,
attributeClasses,
}: RatingQuestionFormProps) => {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const surveyLanguageCodes = extractLanguageCodes(localSurvey.languages);
return (
@@ -51,7 +47,7 @@ export const RatingQuestionForm = ({
/>
<div>
{showSubheader && (
{question.subheader !== undefined && (
<div className="mt-2 inline-flex w-full items-center">
<div className="w-full">
<QuestionFormInput
@@ -67,17 +63,9 @@ export const RatingQuestionForm = ({
attributeClasses={attributeClasses}
/>
</div>
<TrashIcon
className="ml-2 mt-10 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: undefined });
}}
/>
</div>
)}
{!showSubheader && (
{question.subheader === undefined && (
<Button
size="sm"
variant="minimal"
@@ -87,9 +75,7 @@ export const RatingQuestionForm = ({
updateQuestion(questionIdx, {
subheader: createI18nString("", surveyLanguageCodes),
});
setShowSubheader(true);
}}>
{" "}
<PlusIcon className="mr-1 h-4 w-4" />
Add Description
</Button>

View File

@@ -4,7 +4,6 @@ import * as Collapsible from "@radix-ui/react-collapsible";
import { CheckIcon } from "lucide-react";
import Link from "next/link";
import { useEffect, useState } from "react";
import { TSurvey } from "@formbricks/types/surveys";
import { AdvancedOptionToggle } from "@formbricks/ui/AdvancedOptionToggle";
import { Input } from "@formbricks/ui/Input";

View File

@@ -5,7 +5,6 @@ import { ArrowUpRight, CheckIcon } from "lucide-react";
import Link from "next/link";
import { KeyboardEventHandler, useEffect, useState } from "react";
import toast from "react-hot-toast";
import { cn } from "@formbricks/lib/cn";
import { TSurvey } from "@formbricks/types/surveys";
import { AdvancedOptionToggle } from "@formbricks/ui/AdvancedOptionToggle";

View File

@@ -1,6 +1,5 @@
import { Code2Icon, MousePointerClickIcon, SparklesIcon } from "lucide-react";
import { useState } from "react";
import { TActionClass } from "@formbricks/types/actionClasses";
import { TSurvey } from "@formbricks/types/surveys";
import { Input } from "@formbricks/ui/Input";

View File

@@ -2,7 +2,6 @@ import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { GripVerticalIcon, PlusIcon, TrashIcon } from "lucide-react";
import toast from "react-hot-toast";
import { cn } from "@formbricks/lib/cn";
import { createI18nString } from "@formbricks/lib/i18n/utils";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
@@ -13,7 +12,6 @@ import {
TSurveyMultipleChoiceQuestion,
} from "@formbricks/types/surveys";
import { QuestionFormInput } from "@formbricks/ui/QuestionFormInput";
import { isLabelValidForAllLanguages } from "../lib/validation";
interface ChoiceProps {
@@ -70,7 +68,7 @@ export const SelectQuestionChoice = ({
};
return (
<div className="flex w-full items-center gap-2" ref={setNodeRef} style={style}>
<div className="flex w-full gap-2" ref={setNodeRef} style={style}>
{/* drag handle */}
<div
className={cn("flex items-center", choice.id === "other" && "invisible")}
@@ -129,8 +127,7 @@ export const SelectQuestionChoice = ({
/>
)}
</div>
<div className="mt-3 flex items-center gap-2">
<div className="mt-6 flex gap-2">
{question.choices && question.choices.length > 2 && (
<TrashIcon
className="h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"

View File

@@ -3,7 +3,6 @@ import Link from "next/link";
import React, { useEffect, useMemo, useState } from "react";
import { UseFormReturn, useForm, useWatch } from "react-hook-form";
import toast from "react-hot-toast";
import { COLOR_DEFAULTS } from "@formbricks/lib/styling/constants";
import { TEnvironment } from "@formbricks/types/environment";
import { TProduct, TProductStyling } from "@formbricks/types/product";
@@ -20,7 +19,6 @@ import {
FormProvider,
} from "@formbricks/ui/Form";
import { Switch } from "@formbricks/ui/Switch";
import { BackgroundStylingCard } from "./BackgroundStylingCard";
import { CardStylingSettings } from "./CardStylingSettings";
import { FormStylingSettings } from "./FormStylingSettings";

View File

@@ -1,7 +1,5 @@
import { useEffect, useState } from "react";
import { TabBar } from "@formbricks/ui/TabBar";
import { AnimatedSurveyBg } from "./AnimatedSurveyBg";
import { ColorSurveyBg } from "./ColorSurveyBg";
import { UploadImageSurveyBg } from "./ImageSurveyBg";

View File

@@ -1,7 +1,6 @@
"use client";
import { useCallback, useEffect, useRef, useState } from "react";
import { extractLanguageCodes, getEnabledLanguages } from "@formbricks/lib/i18n/utils";
import { structuredClone } from "@formbricks/lib/pollyfills/structuredClone";
import { useDocumentVisibility } from "@formbricks/lib/useDocumentVisibility";
@@ -13,7 +12,6 @@ import { TProduct } from "@formbricks/types/product";
import { TSegment } from "@formbricks/types/segment";
import { TSurvey, TSurveyEditorTabs, TSurveyStyling } from "@formbricks/types/surveys";
import { PreviewSurvey } from "@formbricks/ui/PreviewSurvey";
import { refetchProductAction } from "../actions";
import { LoadingSkeleton } from "./LoadingSkeleton";
import { QuestionsAudienceTabs } from "./QuestionsStylingSettingsTabs";

View File

@@ -4,12 +4,10 @@ import * as Collapsible from "@radix-ui/react-collapsible";
import { CheckIcon } from "lucide-react";
import Link from "next/link";
import { useState } from "react";
import { TPlacement } from "@formbricks/types/common";
import { TSurvey, TSurveyProductOverwrites } from "@formbricks/types/surveys";
import { Label } from "@formbricks/ui/Label";
import { Switch } from "@formbricks/ui/Switch";
import { Placement } from "./Placement";
interface SurveyPlacementCardProps {

View File

@@ -6,7 +6,6 @@ import Link from "next/link";
import { useRouter } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
import { toast } from "react-hot-toast";
import { cn } from "@formbricks/lib/cn";
import { structuredClone } from "@formbricks/lib/pollyfills/structuredClone";
import { isAdvancedSegment } from "@formbricks/lib/segment/utils";
@@ -22,7 +21,6 @@ import { SaveAsNewSegmentModal } from "@formbricks/ui/SaveAsNewSegmentModal";
import { SegmentTitle } from "@formbricks/ui/SegmentTitle";
import { TargetingIndicator } from "@formbricks/ui/TargetingIndicator";
import { UpgradePlanNotice } from "@formbricks/ui/UpgradePlanNotice";
import {
cloneBasicSegmentAction,
createBasicSegmentAction,

View File

@@ -5,12 +5,10 @@ import { SearchIcon } from "lucide-react";
import UnsplashImage from "next/image";
import { useEffect, useRef, useState } from "react";
import toast from "react-hot-toast";
import { TSurveyBackgroundBgType } from "@formbricks/types/surveys";
import { Button } from "@formbricks/ui/Button";
import { Input } from "@formbricks/ui/Input";
import { LoadingSpinner } from "@formbricks/ui/LoadingSpinner";
import { getImagesFromUnsplashAction, triggerDownloadUnsplashImageAction } from "../actions";
interface ImageFromUnsplashSurveyBgProps {

View File

@@ -2,12 +2,10 @@
import { useState } from "react";
import toast from "react-hot-toast";
import { TSurvey, TSurveyQuestion } from "@formbricks/types/surveys";
import { Button } from "@formbricks/ui/Button";
import { Input } from "@formbricks/ui/Input";
import { Label } from "@formbricks/ui/Label";
import { validateId } from "../lib/validation";
interface UpdateQuestionIdProps {

View File

@@ -10,7 +10,6 @@ import {
Trash2Icon,
} from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import { getAccessFlags } from "@formbricks/lib/membership/utils";
import { TActionClass } from "@formbricks/types/actionClasses";
import { TMembershipRole } from "@formbricks/types/memberships";
@@ -18,7 +17,6 @@ import { TSurvey } from "@formbricks/types/surveys";
import { AdvancedOptionToggle } from "@formbricks/ui/AdvancedOptionToggle";
import { Button } from "@formbricks/ui/Button";
import { Input } from "@formbricks/ui/Input";
import { AddActionModal } from "./AddActionModal";
interface WhenToSendCardProps {

View File

@@ -1,5 +1,4 @@
import { getServerSession } from "next-auth";
import { getAdvancedTargetingPermission, getMultiLanguagePermission } from "@formbricks/ee/lib/service";
import { getActionClasses } from "@formbricks/lib/actionClass/service";
import { getAttributeClasses } from "@formbricks/lib/attributeClass/service";
@@ -14,7 +13,6 @@ import { getResponseCountBySurveyId } from "@formbricks/lib/response/service";
import { getSegments } from "@formbricks/lib/segment/service";
import { getSurvey } from "@formbricks/lib/survey/service";
import { ErrorComponent } from "@formbricks/ui/ErrorComponent";
import { SurveyEditor } from "./components/SurveyEditor";
export const generateMetadata = async ({ params }) => {

View File

@@ -43,4 +43,5 @@ export const minimalSurvey: TSurvey = {
resultShareKey: null,
segment: null,
languages: [],
showLanguageSwitch: false,
};

View File

@@ -1,7 +1,6 @@
"use server";
import { getServerSession } from "next-auth";
import { authOptions } from "@formbricks/lib/authOptions";
import { hasUserEnvironmentAccess } from "@formbricks/lib/environment/auth";
import { createSurvey } from "@formbricks/lib/survey/service";

View File

@@ -2,7 +2,6 @@
import { ArrowLeftIcon } from "lucide-react";
import { useRouter } from "next/navigation";
import { Button } from "@formbricks/ui/Button";
export const BackButton = () => {

View File

@@ -2,7 +2,6 @@
import { MenuBar } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/templates/components/MenuBar";
import { useState } from "react";
import { customSurvey } from "@formbricks/lib/templates";
import type { TEnvironment } from "@formbricks/types/environment";
import type { TProduct } from "@formbricks/types/product";
@@ -11,7 +10,6 @@ import { TUser } from "@formbricks/types/user";
import { PreviewSurvey } from "@formbricks/ui/PreviewSurvey";
import { SearchBox } from "@formbricks/ui/SearchBox";
import { TemplateList } from "@formbricks/ui/TemplateList";
import { minimalSurvey } from "../../lib/minimalSurvey";
type TemplateContainerWithPreviewProps = {

View File

@@ -1,9 +1,7 @@
import { getServerSession } from "next-auth";
import { authOptions } from "@formbricks/lib/authOptions";
import { getEnvironment } from "@formbricks/lib/environment/service";
import { getProductByEnvironmentId } from "@formbricks/lib/product/service";
import { TemplateContainerWithPreview } from "./components/TemplateContainer";
const Page = async ({ params }) => {

View File

@@ -1,7 +1,6 @@
"use client";
import { useEffect, useState } from "react";
import { Button } from "@formbricks/ui/Button";
import { Confetti } from "@formbricks/ui/Confetti";

View File

@@ -1,5 +1,4 @@
import { ConfirmationPage } from "@/app/(app)/billing-confirmation/components/ConfirmationPage";
import { PageContentWrapper } from "@formbricks/ui/PageContentWrapper";
export const dynamic = "force-dynamic";

View File

@@ -3,7 +3,6 @@
import { formbricksEnabled } from "@/app/lib/formbricks";
import { usePathname, useSearchParams } from "next/navigation";
import { useCallback, useEffect } from "react";
import formbricks from "@formbricks/js/app";
import { env } from "@formbricks/lib/env";

View File

@@ -1,7 +1,6 @@
"use server";
import { getServerSession } from "next-auth";
import { canUserAccessAttributeClass } from "@formbricks/lib/attributeClass/auth";
import { authOptions } from "@formbricks/lib/authOptions";
import { getSegmentsByAttributeClassName } from "@formbricks/lib/segment/service";

View File

@@ -2,14 +2,12 @@
import { TagIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { convertDateTimeStringShort } from "@formbricks/lib/time";
import { capitalizeFirstLetter } from "@formbricks/lib/utils/strings";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { ErrorComponent } from "@formbricks/ui/ErrorComponent";
import { Label } from "@formbricks/ui/Label";
import { LoadingSpinner } from "@formbricks/ui/LoadingSpinner";
import { getSegmentsByAttributeClassAction } from "../actions";
interface EventActivityTabProps {

View File

@@ -1,10 +1,8 @@
"use client";
import { useMemo, useState } from "react";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { Switch } from "@formbricks/ui/Switch";
import { AttributeDetailModal } from "./AttributeDetailModal";
import { AttributeClassDataRow } from "./AttributeRowData";
import { AttributeTableHeading } from "./AttributeTableHeading";

View File

@@ -1,8 +1,6 @@
import { TagIcon } from "lucide-react";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { ModalWithTabs } from "@formbricks/ui/ModalWithTabs";
import { AttributeActivityTab } from "./AttributeActivityTab";
import { AttributeSettingsTab } from "./AttributeSettingsTab";

View File

@@ -1,5 +1,4 @@
import { TagIcon } from "lucide-react";
import { timeSinceConditionally } from "@formbricks/lib/time";
import { Badge } from "@formbricks/ui/Badge";

View File

@@ -5,7 +5,6 @@ import { ArchiveIcon, ArchiveXIcon } from "lucide-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { updateAttributeClass } from "@formbricks/lib/attributeClass/service";
import { Button } from "@formbricks/ui/Button";
import { Input } from "@formbricks/ui/Input";

View File

@@ -1,5 +1,4 @@
import { HelpCircleIcon } from "lucide-react";
import { Button } from "@formbricks/ui/Button";
export const HowToAddAttributesButton = () => {

View File

@@ -1,6 +1,5 @@
import { PeopleSecondaryNavigation } from "@/app/(app)/environments/[environmentId]/(people)/people/components/PeopleSecondaryNavigation";
import { TagIcon } from "lucide-react";
import { PageContentWrapper } from "@formbricks/ui/PageContentWrapper";
import { PageHeader } from "@formbricks/ui/PageHeader";

View File

@@ -1,12 +1,10 @@
import { PeopleSecondaryNavigation } from "@/app/(app)/environments/[environmentId]/(people)/people/components/PeopleSecondaryNavigation";
import { CircleHelpIcon } from "lucide-react";
import { Metadata } from "next";
import { getAttributeClasses } from "@formbricks/lib/attributeClass/service";
import { Button } from "@formbricks/ui/Button";
import { PageContentWrapper } from "@formbricks/ui/PageContentWrapper";
import { PageHeader } from "@formbricks/ui/PageHeader";
import { AttributeClassesTable } from "./components/AttributeClassesTable";
export const metadata: Metadata = {

View File

@@ -1,7 +1,6 @@
"use server";
import { getServerSession } from "next-auth";
import { authOptions } from "@formbricks/lib/authOptions";
import { canUserAccessPerson } from "@formbricks/lib/person/auth";
import { deletePerson } from "@formbricks/lib/person/service";

View File

@@ -1,6 +1,5 @@
import { formatDistance } from "date-fns";
import { CodeIcon, MousePointerClickIcon, SparklesIcon } from "lucide-react";
import { TAction } from "@formbricks/types/actions";
import { Label } from "@formbricks/ui/Label";
import { Popover, PopoverContent, PopoverTrigger } from "@formbricks/ui/Popover";

View File

@@ -1,5 +1,4 @@
import { ActivityTimeline } from "@/app/(app)/environments/[environmentId]/(people)/people/[personId]/components/ActivityTimeline";
import { getActionsByPersonId } from "@formbricks/lib/action/service";
import { IS_FORMBRICKS_CLOUD } from "@formbricks/lib/constants";
import { getEnvironment } from "@formbricks/lib/environment/service";

View File

@@ -2,7 +2,6 @@ import { TAction } from "@formbricks/types/actions";
import { TEnvironment } from "@formbricks/types/environment";
import { EmptySpaceFiller } from "@formbricks/ui/EmptySpaceFiller";
import { UpgradePlanNotice } from "@formbricks/ui/UpgradePlanNotice";
import { ActivityItemContent, ActivityItemIcon, ActivityItemPopover } from "./ActivityItemComponents";
interface IActivityTimelineProps {

View File

@@ -5,7 +5,6 @@ import { TrashIcon } from "lucide-react";
import { useRouter } from "next/navigation";
import { useState } from "react";
import toast from "react-hot-toast";
import { DeleteDialog } from "@formbricks/ui/DeleteDialog";
interface DeletePersonButtonProps {

View File

@@ -1,6 +1,5 @@
import { ResponseTimeline } from "@/app/(app)/environments/[environmentId]/(people)/people/[personId]/components/ResponseTimeline";
import { getServerSession } from "next-auth";
import { authOptions } from "@formbricks/lib/authOptions";
import { getResponsesByPersonId } from "@formbricks/lib/response/service";
import { getSurveys } from "@formbricks/lib/survey/service";

View File

@@ -3,7 +3,6 @@
import { ResponseFeed } from "@/app/(app)/environments/[environmentId]/(people)/people/[personId]/components/ResponsesFeed";
import { ArrowDownUpIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TEnvironment } from "@formbricks/types/environment";
import { TResponse } from "@formbricks/types/responses";

View File

@@ -1,7 +1,6 @@
"use client";
import { useEffect, useState } from "react";
import { useMembershipRole } from "@formbricks/lib/membership/hooks/useMembershipRole";
import { getAccessFlags } from "@formbricks/lib/membership/utils";
import { replaceHeadlineRecall } from "@formbricks/lib/utils/recall";

View File

@@ -4,7 +4,6 @@ import {
} from "@/app/(app)/environments/[environmentId]/(people)/people/[personId]/components/ActivityItemComponents";
import { ArrowDownUpIcon } from "lucide-react";
import { TrashIcon } from "lucide-react";
import { TAction } from "@formbricks/types/actions";
import { BackIcon } from "@formbricks/ui/icons";

View File

@@ -3,7 +3,6 @@ import { AttributesSection } from "@/app/(app)/environments/[environmentId]/(peo
import { DeletePersonButton } from "@/app/(app)/environments/[environmentId]/(people)/people/[personId]/components/DeletePersonButton";
import { ResponseSection } from "@/app/(app)/environments/[environmentId]/(people)/people/[personId]/components/ResponseSection";
import { getServerSession } from "next-auth";
import { getAttributes } from "@formbricks/lib/attribute/service";
import { getAttributeClasses } from "@formbricks/lib/attributeClass/service";
import { authOptions } from "@formbricks/lib/authOptions";

View File

@@ -1,6 +1,5 @@
import Link from "next/link";
import React from "react";
import { getAttributes } from "@formbricks/lib/attribute/service";
import { getPersonIdentifier } from "@formbricks/lib/person/utils";
import { TPerson } from "@formbricks/types/people";

View File

@@ -1,5 +1,4 @@
import { PeopleSecondaryNavigation } from "@/app/(app)/environments/[environmentId]/(people)/people/components/PeopleSecondaryNavigation";
import { PageContentWrapper } from "@formbricks/ui/PageContentWrapper";
import { PageHeader } from "@formbricks/ui/PageHeader";

View File

@@ -1,6 +1,5 @@
import { PeopleSecondaryNavigation } from "@/app/(app)/environments/[environmentId]/(people)/people/components/PeopleSecondaryNavigation";
import { CircleHelpIcon } from "lucide-react";
import { ITEMS_PER_PAGE } from "@formbricks/lib/constants";
import { getEnvironment } from "@formbricks/lib/environment/service";
import { getPeople, getPeopleCount } from "@formbricks/lib/person/service";
@@ -10,7 +9,6 @@ import { EmptySpaceFiller } from "@formbricks/ui/EmptySpaceFiller";
import { PageContentWrapper } from "@formbricks/ui/PageContentWrapper";
import { PageHeader } from "@formbricks/ui/PageHeader";
import { Pagination } from "@formbricks/ui/Pagination";
import { PersonCard } from "./components/PersonCard";
const Page = async ({

View File

@@ -1,7 +1,6 @@
"use server";
import { getServerSession } from "next-auth";
import { authOptions } from "@formbricks/lib/authOptions";
import { hasUserEnvironmentAccess } from "@formbricks/lib/environment/auth";
import { deleteSegment, getSegment, updateSegment } from "@formbricks/lib/segment/service";

View File

@@ -4,7 +4,6 @@ import { FilterIcon, Trash2 } from "lucide-react";
import { useRouter } from "next/navigation";
import { useMemo, useState } from "react";
import toast from "react-hot-toast";
import { structuredClone } from "@formbricks/lib/pollyfills/structuredClone";
import { isAdvancedSegment } from "@formbricks/lib/segment/utils";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
@@ -15,7 +14,6 @@ import { Button } from "@formbricks/ui/Button";
import { ConfirmDeleteSegmentModal } from "@formbricks/ui/ConfirmDeleteSegmentModal";
import { Input } from "@formbricks/ui/Input";
import { UpgradePlanNotice } from "@formbricks/ui/UpgradePlanNotice";
import { deleteBasicSegmentAction, updateBasicSegmentAction } from "../actions";
type TBasicSegmentSettingsTabProps = {

View File

@@ -1,7 +1,6 @@
import { TActionClass } from "@formbricks/types/actionClasses";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TSegment } from "@formbricks/types/segment";
import { SegmentTableDataRowContainer } from "./SegmentTableDataRowContainer";
type TSegmentTableProps = {

View File

@@ -3,11 +3,9 @@
import { format, formatDistanceToNow } from "date-fns";
import { UsersIcon } from "lucide-react";
import { useState } from "react";
import { TActionClass } from "@formbricks/types/actionClasses";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TSegment, TSegmentWithSurveyNames } from "@formbricks/types/segment";
import { EditSegmentModal } from "./EditSegmentModal";
type TSegmentTableDataRowProps = {

View File

@@ -3,7 +3,6 @@ import { getSurveysBySegmentId } from "@formbricks/lib/survey/service";
import { TActionClass } from "@formbricks/types/actionClasses";
import { TAttributeClass } from "@formbricks/types/attributeClasses";
import { TSegment } from "@formbricks/types/segment";
import { SegmentTableDataRow } from "./SegmentTableDataRow";
type TSegmentTableDataRowProps = {

View File

@@ -1,6 +1,5 @@
import { PeopleSecondaryNavigation } from "@/app/(app)/environments/[environmentId]/(people)/people/components/PeopleSecondaryNavigation";
import { UsersIcon } from "lucide-react";
import { PageContentWrapper } from "@formbricks/ui/PageContentWrapper";
import { PageHeader } from "@formbricks/ui/PageHeader";

View File

@@ -2,7 +2,6 @@
import { Organization } from "@prisma/client";
import { getServerSession } from "next-auth";
import { getIsMultiOrgEnabled } from "@formbricks/ee/lib/service";
import { authOptions } from "@formbricks/lib/authOptions";
import { SHORT_URL_BASE, WEBAPP_URL } from "@formbricks/lib/constants";

View File

@@ -2,14 +2,12 @@
import { Code2Icon, MousePointerClickIcon, SparklesIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { convertDateTimeStringShort } from "@formbricks/lib/time";
import { capitalizeFirstLetter } from "@formbricks/lib/utils/strings";
import { TActionClass } from "@formbricks/types/actionClasses";
import { ErrorComponent } from "@formbricks/ui/ErrorComponent";
import { Label } from "@formbricks/ui/Label";
import { LoadingSpinner } from "@formbricks/ui/LoadingSpinner";
import {
getActionCountInLast7DaysAction,
getActionCountInLast24HoursAction,

View File

@@ -1,11 +1,9 @@
"use client";
import { useState } from "react";
import { useMembershipRole } from "@formbricks/lib/membership/hooks/useMembershipRole";
import { TActionClass } from "@formbricks/types/actionClasses";
import { ErrorComponent } from "@formbricks/ui/ErrorComponent";
import { ActionDetailModal } from "./ActionDetailModal";
interface ActionClassesTableProps {

View File

@@ -1,9 +1,7 @@
import { Code2Icon, MousePointerClickIcon, SparklesIcon } from "lucide-react";
import { TActionClass } from "@formbricks/types/actionClasses";
import { TMembershipRole } from "@formbricks/types/memberships";
import { ModalWithTabs } from "@formbricks/ui/ModalWithTabs";
import { EventActivityTab } from "./ActionActivityTab";
import { ActionSettingsTab } from "./ActionSettingsTab";

View File

@@ -1,5 +1,4 @@
import { Code2Icon, MousePointerClickIcon, SparklesIcon } from "lucide-react";
import { timeSinceConditionally } from "@formbricks/lib/time";
import { TActionClass } from "@formbricks/types/actionClasses";

View File

@@ -12,7 +12,6 @@ import { useMemo, useState } from "react";
import { FormProvider, useForm } from "react-hook-form";
import { toast } from "react-hot-toast";
import { z } from "zod";
import { getAccessFlags } from "@formbricks/lib/membership/utils";
import { TActionClass, TActionClassInput, ZActionClassInput } from "@formbricks/types/actionClasses";
import { TMembershipRole } from "@formbricks/types/memberships";

View File

@@ -3,7 +3,6 @@ import { ActionClassDataRow } from "@/app/(app)/environments/[environmentId]/act
import { ActionTableHeading } from "@/app/(app)/environments/[environmentId]/actions/components/ActionTableHeading";
import { AddActionModal } from "@/app/(app)/environments/[environmentId]/actions/components/AddActionModal";
import { Metadata } from "next";
import { getActionClasses } from "@formbricks/lib/actionClass/service";
import { IS_FORMBRICKS_CLOUD } from "@formbricks/lib/constants";
import { getOrganizationByEnvironmentId } from "@formbricks/lib/organization/service";

View File

@@ -6,7 +6,6 @@ import { useRouter } from "next/navigation";
import { useState } from "react";
import { useForm } from "react-hook-form";
import toast from "react-hot-toast";
import { Button } from "@formbricks/ui/Button";
import { Input } from "@formbricks/ui/Input";
import { Label } from "@formbricks/ui/Label";

View File

@@ -1,7 +1,6 @@
import { MainNavigation } from "@/app/(app)/environments/[environmentId]/components/MainNavigation";
import { TopControlBar } from "@/app/(app)/environments/[environmentId]/components/TopControlBar";
import type { Session } from "next-auth";
import { getIsMultiOrgEnabled } from "@formbricks/ee/lib/service";
import { IS_FORMBRICKS_CLOUD } from "@formbricks/lib/constants";
import { getEnvironment, getEnvironments } from "@formbricks/lib/environment/service";

View File

@@ -2,7 +2,6 @@
import { useRouter } from "next/navigation";
import { useState } from "react";
import { cn } from "@formbricks/lib/cn";
import { TEnvironment } from "@formbricks/types/environment";
import { Label } from "@formbricks/ui/Label";

View File

@@ -26,7 +26,6 @@ import Image from "next/image";
import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
import { cn } from "@formbricks/lib/cn";
import { getAccessFlags } from "@formbricks/lib/membership/utils";
import { capitalizeFirstLetter, truncate } from "@formbricks/lib/utils/strings";
@@ -50,7 +49,6 @@ import {
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@formbricks/ui/DropdownMenu";
import { AddProductModal } from "./AddProductModal";
interface NavigationProps {

View File

@@ -1,6 +1,5 @@
import Link from "next/link";
import React from "react";
import { cn } from "@formbricks/lib/cn";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@formbricks/ui/Tooltip";

View File

@@ -3,7 +3,6 @@
import type { Session } from "next-auth";
import { usePostHog } from "posthog-js/react";
import { useEffect } from "react";
import { env } from "@formbricks/lib/env";
import { TSubscriptionStatus } from "@formbricks/types/organizations";

Some files were not shown because too many files have changed in this diff Show More