diff --git a/apps/formbricks-com/pages/oss-friends.tsx b/apps/formbricks-com/pages/oss-friends.tsx index bed328ba37..fb1521b075 100644 --- a/apps/formbricks-com/pages/oss-friends.tsx +++ b/apps/formbricks-com/pages/oss-friends.tsx @@ -2,7 +2,7 @@ import Layout from "@/components/shared/Layout"; import HeroTitle from "@/components/shared/HeroTitle"; import { Button } from "@formbricks/ui"; -const OSSFriends = [ +export const OSSFriends = [ { name: "BoxyHQ", description: diff --git a/apps/web/app/(app)/environments/[environmentId]/(actionsAndAttributes)/attributes/AttributeDetailModal.tsx b/apps/web/app/(app)/environments/[environmentId]/(actionsAndAttributes)/attributes/AttributeDetailModal.tsx index 9501bc2a03..ea572ddcea 100644 --- a/apps/web/app/(app)/environments/[environmentId]/(actionsAndAttributes)/attributes/AttributeDetailModal.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/(actionsAndAttributes)/attributes/AttributeDetailModal.tsx @@ -24,12 +24,7 @@ export default function AttributeDetailModal({ }, { title: "Settings", - children: ( - - ), + children: , }, ]; diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/SurveyDropDownMenu.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/SurveyDropDownMenu.tsx index d683ece107..5b008a787c 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/SurveyDropDownMenu.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/SurveyDropDownMenu.tsx @@ -1,198 +1,198 @@ -"use client"; - -import { - copyToOtherEnvironmentAction, - deleteSurveyAction, - duplicateSurveyAction, -} from "@/app/(app)/environments/[environmentId]/actions"; -import DeleteDialog from "@/components/shared/DeleteDialog"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuGroup, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/shared/DropdownMenu"; -import LoadingSpinner from "@/components/shared/LoadingSpinner"; -import type { TEnvironment } from "@formbricks/types/v1/environment"; -import type { TSurveyWithAnalytics } from "@formbricks/types/v1/surveys"; -import { - ArrowUpOnSquareStackIcon, - DocumentDuplicateIcon, - EllipsisHorizontalIcon, - EyeIcon, - LinkIcon, - PencilSquareIcon, - TrashIcon, -} from "@heroicons/react/24/solid"; -import Link from "next/link"; -import { useRouter } from "next/navigation"; -import { useState } from "react"; -import toast from "react-hot-toast"; - -interface SurveyDropDownMenuProps { - environmentId: string; - survey: TSurveyWithAnalytics; - environment: TEnvironment; - otherEnvironment: TEnvironment; -} - -export default function SurveyDropDownMenu({ - environmentId, - survey, - environment, - otherEnvironment, -}: SurveyDropDownMenuProps) { - const [isDeleteDialogOpen, setDeleteDialogOpen] = useState(false); - const [loading, setLoading] = useState(false); - const router = useRouter(); - - const handleDeleteSurvey = async (survey) => { - setLoading(true); - try { - await deleteSurveyAction(survey.id); - router.refresh(); - setDeleteDialogOpen(false); - toast.success("Survey deleted successfully."); - } catch (error) { - toast.error("An error occured while deleting survey"); - } - setLoading(false); - }; - - const duplicateSurveyAndRefresh = async (surveyId) => { - setLoading(true); - try { - await duplicateSurveyAction(environmentId, surveyId); - router.refresh(); - toast.success("Survey duplicated successfully."); - } catch (error) { - toast.error("Failed to duplicate the survey."); - } - setLoading(false); - }; - - const copyToOtherEnvironment = async (surveyId) => { - setLoading(true); - try { - await copyToOtherEnvironmentAction(environmentId, surveyId, otherEnvironment.id); - if (otherEnvironment.type === "production") { - toast.success("Survey copied to production env."); - } else if (otherEnvironment.type === "development") { - toast.success("Survey copied to development env."); - } - router.replace(`/environments/${otherEnvironment.id}`); - } catch (error) { - toast.error(`Failed to copy to ${otherEnvironment.type}`); - } - setLoading(false); - }; - if (loading) { - return ( -
- -
- ); - } - return ( - <> - - -
- Open options -
-
- - - - - - Edit - - - - - - {environment.type === "development" ? ( - - - - ) : environment.type === "production" ? ( - - - - ) : null} - {survey.type === "link" && survey.status !== "draft" && ( - <> - - - - Preview Survey - - - - - - - )} - - - - - -
- - handleDeleteSurvey(survey)} - text="Are you sure you want to delete this survey and all of its responses? This action cannot be undone." - /> - - ); -} +"use client"; + +import { + copyToOtherEnvironmentAction, + deleteSurveyAction, + duplicateSurveyAction, +} from "@/app/(app)/environments/[environmentId]/actions"; +import DeleteDialog from "@/components/shared/DeleteDialog"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/shared/DropdownMenu"; +import LoadingSpinner from "@/components/shared/LoadingSpinner"; +import type { TEnvironment } from "@formbricks/types/v1/environment"; +import type { TSurveyWithAnalytics } from "@formbricks/types/v1/surveys"; +import { + ArrowUpOnSquareStackIcon, + DocumentDuplicateIcon, + EllipsisHorizontalIcon, + EyeIcon, + LinkIcon, + PencilSquareIcon, + TrashIcon, +} from "@heroicons/react/24/solid"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import toast from "react-hot-toast"; + +interface SurveyDropDownMenuProps { + environmentId: string; + survey: TSurveyWithAnalytics; + environment: TEnvironment; + otherEnvironment: TEnvironment; +} + +export default function SurveyDropDownMenu({ + environmentId, + survey, + environment, + otherEnvironment, +}: SurveyDropDownMenuProps) { + const [isDeleteDialogOpen, setDeleteDialogOpen] = useState(false); + const [loading, setLoading] = useState(false); + const router = useRouter(); + + const handleDeleteSurvey = async (survey) => { + setLoading(true); + try { + await deleteSurveyAction(survey.id); + router.refresh(); + setDeleteDialogOpen(false); + toast.success("Survey deleted successfully."); + } catch (error) { + toast.error("An error occured while deleting survey"); + } + setLoading(false); + }; + + const duplicateSurveyAndRefresh = async (surveyId) => { + setLoading(true); + try { + await duplicateSurveyAction(environmentId, surveyId); + router.refresh(); + toast.success("Survey duplicated successfully."); + } catch (error) { + toast.error("Failed to duplicate the survey."); + } + setLoading(false); + }; + + const copyToOtherEnvironment = async (surveyId) => { + setLoading(true); + try { + await copyToOtherEnvironmentAction(environmentId, surveyId, otherEnvironment.id); + if (otherEnvironment.type === "production") { + toast.success("Survey copied to production env."); + } else if (otherEnvironment.type === "development") { + toast.success("Survey copied to development env."); + } + router.replace(`/environments/${otherEnvironment.id}`); + } catch (error) { + toast.error(`Failed to copy to ${otherEnvironment.type}`); + } + setLoading(false); + }; + if (loading) { + return ( +
+ +
+ ); + } + return ( + <> + + +
+ Open options +
+
+ + + + + + Edit + + + + + + {environment.type === "development" ? ( + + + + ) : environment.type === "production" ? ( + + + + ) : null} + {survey.type === "link" && survey.status !== "draft" && ( + <> + + + + Preview Survey + + + + + + + )} + + + + + +
+ + handleDeleteSurvey(survey)} + text="Are you sure you want to delete this survey and all of its responses? This action cannot be undone." + /> + + ); +} diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/SurveyStarter.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/SurveyStarter.tsx index afaf8a7130..21f23f8135 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/SurveyStarter.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/SurveyStarter.tsx @@ -1,60 +1,60 @@ -"use client"; -import { Template } from "@/../../packages/types/templates"; -import { createSurveyAction } from "./actions"; -import TemplateList from "@/app/(app)/environments/[environmentId]/surveys/templates/TemplateList"; -import LoadingSpinner from "@/components/shared/LoadingSpinner"; -import type { TEnvironment } from "@formbricks/types/v1/environment"; -import type { TProduct } from "@formbricks/types/v1/product"; -import { useRouter } from "next/navigation"; -import { useState } from "react"; -import { toast } from "react-hot-toast"; - -export default function SurveyStarter({ - environmentId, - environment, - product, -}: { - environmentId: string; - environment: TEnvironment; - product: TProduct; -}) { - const [isCreateSurveyLoading, setIsCreateSurveyLoading] = useState(false); - const router = useRouter(); - const newSurveyFromTemplate = async (template: Template) => { - setIsCreateSurveyLoading(true); - const augmentedTemplate = { - ...template.preset, - type: environment?.widgetSetupCompleted ? "web" : "link", - }; - try { - const survey = await createSurveyAction(environmentId, augmentedTemplate); - router.push(`/environments/${environmentId}/surveys/${survey.id}/edit`); - } catch (e) { - toast.error("An error occured creating a new survey"); - setIsCreateSurveyLoading(false); - } - }; - return ( -
- {isCreateSurveyLoading ? ( - - ) : ( - <> -
-

- You're all set! Time to create your first survey. -

-
- { - newSurveyFromTemplate(template); - }} - environment={environment} - product={product} - /> - - )} -
- ); -} +"use client"; +import { Template } from "@/../../packages/types/templates"; +import { createSurveyAction } from "./actions"; +import TemplateList from "@/app/(app)/environments/[environmentId]/surveys/templates/TemplateList"; +import LoadingSpinner from "@/components/shared/LoadingSpinner"; +import type { TEnvironment } from "@formbricks/types/v1/environment"; +import type { TProduct } from "@formbricks/types/v1/product"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import { toast } from "react-hot-toast"; + +export default function SurveyStarter({ + environmentId, + environment, + product, +}: { + environmentId: string; + environment: TEnvironment; + product: TProduct; +}) { + const [isCreateSurveyLoading, setIsCreateSurveyLoading] = useState(false); + const router = useRouter(); + const newSurveyFromTemplate = async (template: Template) => { + setIsCreateSurveyLoading(true); + const augmentedTemplate = { + ...template.preset, + type: environment?.widgetSetupCompleted ? "web" : "link", + }; + try { + const survey = await createSurveyAction(environmentId, augmentedTemplate); + router.push(`/environments/${environmentId}/surveys/${survey.id}/edit`); + } catch (e) { + toast.error("An error occured creating a new survey"); + setIsCreateSurveyLoading(false); + } + }; + return ( +
+ {isCreateSurveyLoading ? ( + + ) : ( + <> +
+

+ You're all set! Time to create your first survey. +

+
+ { + newSurveyFromTemplate(template); + }} + environment={environment} + product={product} + /> + + )} +
+ ); +} diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/responses/TagsCombobox.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/responses/TagsCombobox.tsx index a6baedd5ae..4ef0405778 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/responses/TagsCombobox.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/responses/TagsCombobox.tsx @@ -87,8 +87,8 @@ const TagsCombobox: React.FC = ({ onKeyDown={(e) => { if (e.key === "Enter" && searchValue !== "") { if ( - !tagsToSearch?.find( - (tag) => tag?.label?.toLowerCase().includes(searchValue?.toLowerCase()) + !tagsToSearch?.find((tag) => + tag?.label?.toLowerCase().includes(searchValue?.toLowerCase()) ) ) { createTag?.(searchValue); diff --git a/packages/lib/services/environment.ts b/packages/lib/services/environment.ts index 550e43bb40..9b2e3c7ab5 100644 --- a/packages/lib/services/environment.ts +++ b/packages/lib/services/environment.ts @@ -38,42 +38,40 @@ export const getEnvironment = cache(async (environmentId: string): Promise => { - let productPrisma; - try { - productPrisma = await prisma.product.findFirst({ - where: { - id: productId, - }, - include:{ - environments:true - } - }); +export const getEnvironments = cache(async (productId: string): Promise => { + let productPrisma; + try { + productPrisma = await prisma.product.findFirst({ + where: { + id: productId, + }, + include: { + environments: true, + }, + }); - if (!productPrisma) { - throw new ResourceNotFoundError("Product", productId); - } - } catch (error) { - if (error instanceof Prisma.PrismaClientKnownRequestError) { - throw new DatabaseError("Database operation failed"); - } - throw error; + if (!productPrisma) { + throw new ResourceNotFoundError("Product", productId); } - - const environments:TEnvironment[]=[]; - for(let environment of productPrisma.environments){ - let targetEnvironment:TEnvironment=ZEnvironment.parse(environment); - environments.push(targetEnvironment); - } - - try { - return environments; - } catch (error) { - if (error instanceof z.ZodError) { - console.error(JSON.stringify(error.errors, null, 2)); - } - throw new ValidationError("Data validation of environments array failed"); + } catch (error) { + if (error instanceof Prisma.PrismaClientKnownRequestError) { + throw new DatabaseError("Database operation failed"); } + throw error; } -); \ No newline at end of file + + const environments: TEnvironment[] = []; + for (let environment of productPrisma.environments) { + let targetEnvironment: TEnvironment = ZEnvironment.parse(environment); + environments.push(targetEnvironment); + } + + try { + return environments; + } catch (error) { + if (error instanceof z.ZodError) { + console.error(JSON.stringify(error.errors, null, 2)); + } + throw new ValidationError("Data validation of environments array failed"); + } +}); diff --git a/packages/lib/services/person.ts b/packages/lib/services/person.ts index 75e5df446f..5bdf0f02bb 100644 --- a/packages/lib/services/person.ts +++ b/packages/lib/services/person.ts @@ -33,13 +33,10 @@ type TransformPersonInput = { }; export const transformPrismaPerson = (person: TransformPersonInput): TPerson => { - const attributes = person.attributes.reduce( - (acc, attr) => { - acc[attr.attributeClass.name] = attr.value; - return acc; - }, - {} as Record - ); + const attributes = person.attributes.reduce((acc, attr) => { + acc[attr.attributeClass.name] = attr.value; + return acc; + }, {} as Record); return { id: person.id, diff --git a/packages/lib/services/product.ts b/packages/lib/services/product.ts index dc707f5313..12451da4e9 100644 --- a/packages/lib/services/product.ts +++ b/packages/lib/services/product.ts @@ -41,4 +41,3 @@ export const getProductByEnvironmentId = cache(async (environmentId: string): Pr throw new ValidationError("Data validation of product failed"); } }); - diff --git a/turbo.json b/turbo.json index df4bbec873..3285d3445d 100644 --- a/turbo.json +++ b/turbo.json @@ -77,6 +77,7 @@ ] }, "db:setup": { + "cache": false, "outputs": [] }, "go": {