mirror of
https://github.com/formbricks/formbricks.git
synced 2026-03-24 00:45:50 -05:00
Compare commits
1 Commits
feat/icon-
...
fix/licens
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9833ba6b26 |
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,6 +1,7 @@
|
||||
name: Bug report
|
||||
description: "Found a bug? Please fill out the sections below. \U0001F44D"
|
||||
type: bug
|
||||
labels:
|
||||
- bug
|
||||
body:
|
||||
- type: textarea
|
||||
id: issue-summary
|
||||
|
||||
3
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
3
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,6 +1,7 @@
|
||||
name: Feature request
|
||||
description: "Suggest an idea for this project \U0001F680"
|
||||
type: feature
|
||||
labels:
|
||||
- enhancement
|
||||
body:
|
||||
- type: textarea
|
||||
id: problem-description
|
||||
|
||||
11
.github/ISSUE_TEMPLATE/task.yml
vendored
11
.github/ISSUE_TEMPLATE/task.yml
vendored
@@ -1,11 +0,0 @@
|
||||
name: Task (internal)
|
||||
description: "Template for creating a task. Used by the Formbricks Team only \U0001f4e5"
|
||||
type: task
|
||||
body:
|
||||
- type: textarea
|
||||
id: task-summary
|
||||
attributes:
|
||||
label: Task description
|
||||
description: A clear detailed-rich description of the task.
|
||||
validations:
|
||||
required: true
|
||||
2
LICENSE
2
LICENSE
@@ -2,7 +2,7 @@ Copyright (c) 2024 Formbricks GmbH
|
||||
|
||||
Portions of this software are licensed as follows:
|
||||
|
||||
- All content that resides under the "apps/web/modules/ee" directory of this repository, if these directories exist, is licensed under the license defined in "apps/web/modules/ee/LICENSE".
|
||||
- All content that resides under the "packages/ee/", "apps/web/modules/ee" & "apps/web/app/(ee)" directories of this repository, if these directories exist, is licensed under the license defined in "packages/ee/LICENSE".
|
||||
- All content that resides under the "packages/js/", "packages/react-native/" and "packages/api/" directories of this repository, if that directories exist, is licensed under the "MIT" license as defined in the "LICENSE" files of these packages.
|
||||
- All third party components incorporated into the Formbricks Software are licensed under the original license provided by the owner of the applicable component.
|
||||
- Content outside of the above mentioned directories or restrictions above is available under the "AGPLv3" license as defined below.
|
||||
|
||||
@@ -228,7 +228,7 @@ The Formbricks core application is licensed under the [AGPLv3 Open Source Licens
|
||||
|
||||
### The Enterprise Edition
|
||||
|
||||
Additional to the AGPL licensed Formbricks core, this repository contains code licensed under an Enterprise license. The [code](https://github.com/formbricks/formbricks/tree/main/apps/web/modules/ee) and [license](https://github.com/formbricks/formbricks/blob/main/apps/web/modules/ee/LICENSE) for the enterprise functionality can be found in the `/apps/web/modules/ee` folder of this repository. This additional functionality is not part of the AGPLv3 licensed Formbricks core and is designed to meet the needs of larger teams and enterprises. This advanced functionality is already included in the Docker images, but you need an [Enterprise License Key](https://formbricks.com/docs/self-hosting/enterprise) to unlock it.
|
||||
Additional to the AGPL licensed Formbricks core, this repository contains code licensed under an Enterprise license. The [code](https://github.com/formbricks/formbricks/tree/main/packages/ee) and [license](https://github.com/formbricks/formbricks/blob/main/packages/ee/LICENSE) for the enterprise functionality can be found in the `/packages/ee` folder of this repository. This additional functionality is not part of the AGPLv3 licensed Formbricks core and is designed to meet the needs of larger teams and enterprises. This advanced functionality is already included in the Docker images, but you need an [Enterprise License Key](https://formbricks.com/docs/self-hosting/enterprise) to unlock it.
|
||||
|
||||
### White-Labeling Formbricks and Other Licensing Needs
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@@ -12,6 +12,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@formbricks/js": "workspace:*",
|
||||
"@formbricks/ui": "workspace:*",
|
||||
"lucide-react": "0.452.0",
|
||||
"next": "15.0.3",
|
||||
"react": "19.0.0-rc-ed15d500-20241110",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { AppProps } from "next/app";
|
||||
import Head from "next/head";
|
||||
import "../globals.css";
|
||||
import "@formbricks/ui/globals.css";
|
||||
|
||||
const App = ({ Component, pageProps }: AppProps) => {
|
||||
return (
|
||||
|
||||
BIN
apps/docs/app/best-practices/contact-form/images/embed.png
Normal file
BIN
apps/docs/app/best-practices/contact-form/images/embed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@@ -127,10 +127,10 @@ Locate that file. We are using the [Tailwind Template “Syntax”](https://tail
|
||||
<CodeGroup title="Entire Widget">
|
||||
|
||||
```tsx
|
||||
import { Button } from "@/modules/ui/components/Button";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/modules/ui/popover";
|
||||
import { useRouter } from "next/router";
|
||||
import { useState } from "react";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@formbricks/ui/components/Popover";
|
||||
import { handleFeedbackSubmit, updateFeedback } from "../../lib/handleFeedbackSubmit";
|
||||
|
||||
export const DocsFeedback = () => {
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@formbricks/ui/components/Accordion";
|
||||
import { FaqJsonLdComponent } from "./FAQPageJsonLd";
|
||||
|
||||
const FAQ_DATA = [
|
||||
{
|
||||
question: "What is an environment ID?",
|
||||
answer: () => (
|
||||
<>
|
||||
The environment ID is a unique identifier associated with each Environment in Formbricks,
|
||||
distinguishing between different setups like production, development, etc.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
question: "How can I implement authentication for the Formbricks API?",
|
||||
answer: () => (
|
||||
<>
|
||||
Formbricks provides 2 types of API keys for each environment ie development and production. You can
|
||||
generate, view, and manage these keys in the Settings section on the Admin dashboard. Include the API
|
||||
key in your requests to authenticate and gain access to Formbricks functionalities.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
question: "Can I run the deployment shell script on any server?",
|
||||
answer: () => (
|
||||
<>
|
||||
You can run it on any machine you own as long as its running a <b> Linux Ubuntu </b> distribution. And
|
||||
to forward the requests, make sure you have an <b>A record</b> setup for your domain pointing to the
|
||||
server.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
question: "Can I self-host Formbricks?",
|
||||
answer: () => (
|
||||
<>
|
||||
Absolutely! We provide an option for users to host Formbricks on their own server, ensuring even more
|
||||
control over data and compliance. And the best part? Self-hosting is available for free, always. For
|
||||
documentation on self hosting, click{" "}
|
||||
<a href="/self-hosting/deployment" className="text-brand-dark dark:text-brand-light">
|
||||
here
|
||||
</a>
|
||||
.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
question: "How can I change Button texts in my survey?",
|
||||
answer: () => (
|
||||
<>
|
||||
For the question that you want to change the button text, click on the <b>Show Advanced Settings</b>{" "}
|
||||
toggle and change the button label in the <b>Button Text</b> field.
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
export const faqJsonLdData = FAQ_DATA.map((faq) => ({
|
||||
questionName: faq.question,
|
||||
acceptedAnswerText: faq.answer(),
|
||||
}));
|
||||
|
||||
export const FAQ = () => {
|
||||
return (
|
||||
<>
|
||||
<FaqJsonLdComponent data={faqJsonLdData} />
|
||||
<Accordion type="single" collapsible>
|
||||
{FAQ_DATA.map((faq, index) => (
|
||||
<AccordionItem key={`item-${index}`} value={`item-${index + 1}`} className="not-prose mb-0 mt-0">
|
||||
<AccordionTrigger>{faq.question}</AccordionTrigger>
|
||||
<AccordionContent>{faq.answer()}</AccordionContent>
|
||||
</AccordionItem>
|
||||
))}
|
||||
</Accordion>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { FAQPageJsonLd } from "next-seo";
|
||||
|
||||
export const FaqJsonLdComponent = ({ data }) => {
|
||||
const faqEntities = data.map(({ question, answer }) => ({
|
||||
questionName: question,
|
||||
acceptedAnswerText: answer,
|
||||
}));
|
||||
|
||||
return <FAQPageJsonLd mainEntity={faqEntities} />;
|
||||
};
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
@@ -1,89 +0,0 @@
|
||||
import { MdxImage } from "@/components/MdxImage";
|
||||
|
||||
import CreatedVariables from "./images/created-variables.webp";
|
||||
import InputVariables from "./images/input-variables.webp";
|
||||
import LogicWithVariables from "./images/logic-with-variables.webp";
|
||||
import VariablesCard from "./images/variables-card.webp";
|
||||
import VariablesUsage from "./images/variables-usage.webp";
|
||||
|
||||
export const metadata = {
|
||||
title: "Variables",
|
||||
description: "Add variabeles to your surveys to transform your survey into a quiz",
|
||||
};
|
||||
|
||||
# Variables
|
||||
|
||||
Variables are a powerful feature in Formbricks that allows you to keep track of data variables when user fills a form. This feature is especially useful when you want to use your survey as a quiz.
|
||||
|
||||
## Types of Variables
|
||||
|
||||
There are two types of variables you can add to your survey:
|
||||
|
||||
1. **Text**: You can add text variables to your survey to capture text data.
|
||||
2. **Number**: You can add number variables to your survey to capture number data.
|
||||
|
||||
## How to Add Variables
|
||||
|
||||
1. Edit the survey you want to add variables to & switch to the Questions tab and scroll down to the bottom of the page. You will see a section called **Variables**.
|
||||
|
||||
<MdxImage
|
||||
src={VariablesCard}
|
||||
alt="Variables card"
|
||||
quality="100"
|
||||
className="max-w-full rounded-lg sm:max-w-3xl"
|
||||
/>
|
||||
|
||||
2. Now click on it to add a new variable ID. You can add as many variables as you want. You can also choose the type of variable you want to add along with the default value.
|
||||
|
||||
<MdxImage
|
||||
src={InputVariables}
|
||||
alt="add variables"
|
||||
quality="100"
|
||||
className="max-w-full rounded-lg sm:max-w-3xl"
|
||||
/>
|
||||
|
||||
<MdxImage
|
||||
src={CreatedVariables}
|
||||
alt="created variables"
|
||||
quality="100"
|
||||
className="max-w-full rounded-lg sm:max-w-3xl"
|
||||
/>
|
||||
|
||||
## Use case:
|
||||
|
||||
- **Quiz**: You can use variables to create a quiz. For example, you can add a variable `score` and update it every time a user answers a question. You can also use the variable for recall to show the final score to the user.
|
||||
|
||||
- **Personalisation**: You can use variables to store user data and personalise the survey experience. For example, you can add a variable `full_name` and update it every time a user fills in their first name and last name. You can use the variable to personalise the survey experience by addressing the user with their full name.
|
||||
|
||||
## How is it different from Hidden Fields?
|
||||
|
||||
Variables are different from hidden fields in the following ways:
|
||||
|
||||
1. **Setting**: Hidden fields can be set through query parameters or `formbricks.init`, but the variables can only be set either during creation or dynamically by using logic actions.
|
||||
2. **Updating**: Hidden fields cannot be set again, but the value of variables can be updated while the user fills the survey.
|
||||
3. **Type**: Hidden fields can only store text data, but variables can store both text and number data.
|
||||
|
||||
## How to use Variables
|
||||
|
||||
1. Once you have added the variables to your survey, you'll be able to access them in the logic editor. You can use the variables to create logic actions and conditions.
|
||||
|
||||
<MdxImage
|
||||
src={VariablesUsage}
|
||||
alt="Variables usage"
|
||||
quality="100"
|
||||
className="max-w-full rounded-lg sm:max-w-3xl"
|
||||
/>
|
||||
|
||||
2. You can create logic based on the variables and questions in your survey and can update the variables based on the user's response.
|
||||
|
||||
<MdxImage
|
||||
src={LogicWithVariables}
|
||||
alt="Logic with variables"
|
||||
quality="100"
|
||||
className="max-w-full rounded-lg sm:max-w-3xl"
|
||||
/>
|
||||
|
||||
<Note>
|
||||
To know more about how to use logic in Formbricks, check out the [Conditional
|
||||
Logic](/global/conditional-logic).
|
||||
</Note>
|
||||
@@ -1,54 +0,0 @@
|
||||
export const metadata = {
|
||||
title: "Cluster Setup for Formbricks",
|
||||
description: "Learn how to set up Formbricks in a multi-instance cluster configuration for high availability and scalability.",
|
||||
};
|
||||
|
||||
#### Self-Hosting
|
||||
|
||||
# Cluster Setup
|
||||
|
||||
<Note>
|
||||
Running Formbricks in a multi-instance cluster configuration is an Enterprise Edition feature and requires an enterprise license key.
|
||||
</Note>
|
||||
|
||||
## Overview
|
||||
|
||||
Running Formbricks as a cluster of multiple instances offers several key advantages:
|
||||
|
||||
- **High Availability**: Ensure your surveys remain accessible even if some instances fail
|
||||
- **Load Distribution**: Handle higher traffic by distributing requests across multiple instances
|
||||
- **Scalability**: Easily scale horizontally by adding more instances as your needs grow
|
||||
- **Zero-Downtime Updates**: Rolling updates without service interruption
|
||||
|
||||
## Requirements
|
||||
|
||||
To run Formbricks in a cluster setup, you'll need:
|
||||
|
||||
- Enterprise Edition license key
|
||||
- Shared PostgreSQL database
|
||||
- Shared Redis cache for session management and caching
|
||||
- Load balancer to distribute traffic
|
||||
|
||||
## Redis Configuration
|
||||
|
||||
<Note>
|
||||
Redis integration is an Enterprise Edition feature and requires an enterprise license key.
|
||||
</Note>
|
||||
|
||||
Configure Redis by adding the following environment variables to your instances:
|
||||
|
||||
```sh {{ title: 'env file' }}
|
||||
REDIS_URL=redis://your-redis-host:6379
|
||||
REDIS_HTTP_URL=http://your-redis-host:8000
|
||||
```
|
||||
|
||||
## Coming Soon
|
||||
|
||||
We're working on comprehensive Kubernetes deployment instructions to make cluster setup even easier. This will include:
|
||||
|
||||
- Kubernetes manifests
|
||||
- Helm charts
|
||||
- Detailed scaling configurations
|
||||
- Production-ready deployment examples
|
||||
|
||||
Stay tuned for updates.
|
||||
@@ -19,7 +19,7 @@ The Formbricks Core source code is licensed under AGPLv3 and available on GitHub
|
||||
|
||||
## Enterprise Edition License
|
||||
|
||||
Additional to the AGPLv3 licensed Formbricks core, the Formbricks repository contains code licensed under our **[Enterprise License](https://github.com/formbricks/formbricks/blob/main/apps/web/modules/ee/LICENSE)**. This additional functionality is not part of the AGPLv3 licensed Formbricks core and is designed to meet the needs of larger teams and enterprises. This advanced functionality is already included in the Docker images, but you need an **Enterprise License Key** to unlock it. For the pricing, please refer to [Formbricks Pricing](https://formbricks.com/pricing).
|
||||
Additional to the AGPLv3 licensed Formbricks core, the Formbricks repository contains code licensed under our **[Enterprise License](https://github.com/formbricks/formbricks/blob/main/packages/ee/LICENSE)**. This additional functionality is not part of the AGPLv3 licensed Formbricks core and is designed to meet the needs of larger teams and enterprises. This advanced functionality is already included in the Docker images, but you need an **Enterprise License Key** to unlock it. For the pricing, please refer to [Formbricks Pricing](https://formbricks.com/pricing).
|
||||
|
||||
### When do I need an Enterprise License?
|
||||
|
||||
@@ -64,7 +64,7 @@ The Formbricks core application is licensed under the **[AGPLv3 Open Source Lice
|
||||
|
||||
### The Enterprise Edition
|
||||
|
||||
Additional to the AGPL licensed Formbricks core, this repository contains code licensed under an Enterprise license. The **[code](https://github.com/formbricks/formbricks/tree/main/apps/web/modules/ee)** and **[license](https://github.com/formbricks/formbricks/blob/main/apps/web/modules/ee/LICENSE)** for the enterprise functionality can be found in the `/apps/web/modules/ee` folder of this repository. This additional functionality is not part of the AGPLv3 licensed Formbricks core and is designed to meet the needs of larger teams and enterprises. This advanced functionality is already included in the Docker images, but you need an **[Enterprise License Key](https://formbricks.com/docs/self-hosting/enterprise)** to unlock it.
|
||||
Additional to the AGPL licensed Formbricks core, this repository contains code licensed under an Enterprise License. The **[code](https://github.com/formbricks/formbricks/tree/main/packages/ee)** and **[license](https://github.com/formbricks/formbricks/blob/main/packages/ee/LICENSE)** for the enterprise functionality can be found in the `/packages/ee` folder of this repository. This additional functionality is not part of the AGPLv3 licensed Formbricks core and is designed to meet the needs of larger teams and enterprises. This advanced functionality is already included in the Docker images, but you need an **Enterprise License Key** to unlock it.
|
||||
|
||||
## White-Labeling Formbricks and Other Licensing Needs
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ export const navigation: Array<NavGroup> = [
|
||||
title: "Add Image/Video to Question",
|
||||
href: "/global/add-image-or-video-question",
|
||||
},
|
||||
{ title: "Variables", href: "/global/variables" },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -86,7 +85,6 @@ export const navigation: Array<NavGroup> = [
|
||||
title: "Add Image/Video to Question",
|
||||
href: "/global/add-image-or-video-question",
|
||||
},
|
||||
{ title: "Variables", href: "/global/variables" },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -143,7 +141,6 @@ export const navigation: Array<NavGroup> = [
|
||||
{ title: "Configuration", href: "/self-hosting/configuration" },
|
||||
{ title: "Integrations", href: "/self-hosting/integrations" },
|
||||
{ title: "License", href: "/self-hosting/license" },
|
||||
{ title: "Cluster Setup", href: "/self-hosting/cluster-setup" },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ const withMDX = nextMDX({
|
||||
const nextConfig = {
|
||||
basePath: "/docs",
|
||||
pageExtensions: ["js", "jsx", "ts", "tsx", "mdx"],
|
||||
transpilePackages: ["@formbricks/lib"],
|
||||
transpilePackages: ["@formbricks/ui", "@formbricks/lib"],
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"@docsearch/react": "3.6.2",
|
||||
"@formbricks/lib": "workspace:*",
|
||||
"@formbricks/types": "workspace:*",
|
||||
"@formbricks/ui": "workspace:*",
|
||||
"@headlessui/react": "2.1.9",
|
||||
"@headlessui/tailwindcss": "0.2.1",
|
||||
"@mapbox/rehype-prism": "0.9.0",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import headlessuiPlugin from "@headlessui/tailwindcss";
|
||||
import forms from "@tailwindcss/forms";
|
||||
import typographyPlugin from "@tailwindcss/typography";
|
||||
import { type Config } from "tailwindcss";
|
||||
import defaultTheme from "tailwindcss/defaultTheme";
|
||||
@@ -81,5 +82,5 @@ export default {
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [typographyPlugin, headlessuiPlugin],
|
||||
plugins: [typographyPlugin, headlessuiPlugin, forms],
|
||||
} satisfies Config;
|
||||
|
||||
@@ -10,7 +10,11 @@ const getAbsolutePath = (value: string) => {
|
||||
};
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ["../src/**/*.mdx", "../../web/modules/ui/**/stories.@(js|jsx|mjs|ts|tsx)"],
|
||||
stories: [
|
||||
"../src/**/*.mdx",
|
||||
"../src/**/*.stories.@(js|jsx|mjs|ts|tsx)",
|
||||
"../../../packages/ui/**/stories.@(js|jsx|mjs|ts|tsx)",
|
||||
],
|
||||
addons: [
|
||||
getAbsolutePath("@storybook/addon-onboarding"),
|
||||
getAbsolutePath("@storybook/addon-links"),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Preview } from "@storybook/react";
|
||||
import "@formbricks/web/modules/ui/globals.css";
|
||||
import "../../../packages/ui/globals.css";
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"clean": "rimraf .turbo node_modules dist storybook-static"
|
||||
},
|
||||
"dependencies": {
|
||||
"@formbricks/ui": "workspace:*",
|
||||
"eslint-plugin-react-refresh": "0.4.12",
|
||||
"react": "19.0.0-rc-ed15d500-20241110",
|
||||
"react-dom": "19.0.0-rc-ed15d500-20241110"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
import base from "../web/tailwind.config";
|
||||
import base from "../../packages/ui/tailwind.config";
|
||||
|
||||
export default {
|
||||
...base,
|
||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}", "../web/modules/ui/**/*.{js,ts,jsx,tsx}"],
|
||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}", "../../packages/ui/**/*.{js,ts,jsx,tsx}"],
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import react from "@vitejs/plugin-react";
|
||||
import path from "path";
|
||||
import { defineConfig } from "vite";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
@@ -8,9 +7,4 @@ export default defineConfig({
|
||||
define: {
|
||||
"process.env": {},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "../web"),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { ArrowRight } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useRouter } from "next/navigation";
|
||||
@@ -8,6 +7,7 @@ import { useEffect } from "react";
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { TEnvironment } from "@formbricks/types/environment";
|
||||
import { TProductConfigChannel } from "@formbricks/types/product";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { OnboardingSetupInstructions } from "./OnboardingSetupInstructions";
|
||||
|
||||
interface ConnectWithFormbricksProps {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { inviteOrganizationMemberAction } from "@/app/(app)/(onboarding)/organizations/actions";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { FormControl, FormError, FormField, FormItem, FormLabel } from "@/modules/ui/components/form";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useRouter } from "next/navigation";
|
||||
@@ -11,6 +8,9 @@ import { FormProvider, useForm } from "react-hook-form";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { z } from "zod";
|
||||
import { TOrganization } from "@formbricks/types/organizations";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { FormControl, FormError, FormField, FormItem, FormLabel } from "@formbricks/ui/components/Form";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
|
||||
interface InviteOrganizationMemberProps {
|
||||
organization: TOrganization;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { CodeBlock } from "@/modules/ui/components/code-block";
|
||||
import { Html5Icon, NpmIcon } from "@/modules/ui/components/icons";
|
||||
import { TabBar } from "@/modules/ui/components/tab-bar";
|
||||
import { useTranslations } from "next-intl";
|
||||
import "prismjs/themes/prism.css";
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { TProductConfigChannel } from "@formbricks/types/product";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { CodeBlock } from "@formbricks/ui/components/CodeBlock";
|
||||
import { TabBar } from "@formbricks/ui/components/TabBar";
|
||||
import { Html5Icon, NpmIcon } from "@formbricks/ui/components/icons";
|
||||
|
||||
const tabs = [
|
||||
{ id: "html", label: "HTML", icon: <Html5Icon /> },
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { InviteOrganizationMember } from "@/app/(app)/(onboarding)/environments/[environmentId]/connect/components/InviteOrganizationMember";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Header } from "@/modules/ui/components/header";
|
||||
import { XIcon } from "lucide-react";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
@@ -8,6 +6,8 @@ import { notFound, redirect } from "next/navigation";
|
||||
import { authOptions } from "@formbricks/lib/authOptions";
|
||||
import { getMembershipByUserIdOrganizationId } from "@formbricks/lib/membership/service";
|
||||
import { getOrganizationByEnvironmentId } from "@formbricks/lib/organization/service";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Header } from "@formbricks/ui/components/Header";
|
||||
|
||||
interface InvitePageProps {
|
||||
params: Promise<{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { ConnectWithFormbricks } from "@/app/(app)/(onboarding)/environments/[environmentId]/connect/components/ConnectWithFormbricks";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Header } from "@/modules/ui/components/header";
|
||||
import { XIcon } from "lucide-react";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { WEBAPP_URL } from "@formbricks/lib/constants";
|
||||
import { getEnvironment } from "@formbricks/lib/environment/service";
|
||||
import { getProductByEnvironmentId } from "@formbricks/lib/product/service";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Header } from "@formbricks/ui/components/Header";
|
||||
|
||||
interface ConnectPageProps {
|
||||
params: Promise<{
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { XMTemplateList } from "@/app/(app)/(onboarding)/environments/[environmentId]/xm-templates/components/XMTemplateList";
|
||||
import { getOrganizationIdFromEnvironmentId } from "@/lib/utils/helper";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Header } from "@/modules/ui/components/header";
|
||||
import { XIcon } from "lucide-react";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
@@ -9,6 +7,8 @@ import { authOptions } from "@formbricks/lib/authOptions";
|
||||
import { getEnvironment } from "@formbricks/lib/environment/service";
|
||||
import { getProductByEnvironmentId, getUserProducts } from "@formbricks/lib/product/service";
|
||||
import { getUser } from "@formbricks/lib/user/service";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Header } from "@formbricks/ui/components/Header";
|
||||
|
||||
interface XMTemplatePageProps {
|
||||
params: Promise<{
|
||||
|
||||
@@ -3,20 +3,6 @@
|
||||
import { formbricksLogout } from "@/app/lib/formbricks";
|
||||
import FBLogo from "@/images/formbricks-wordmark.svg";
|
||||
import { CreateOrganizationModal } from "@/modules/organization/components/CreateOrganizationModal";
|
||||
import { ProfileAvatar } from "@/modules/ui/components/avatars";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/modules/ui/components/dropdown-menu";
|
||||
import { ArrowUpRightIcon, ChevronRightIcon, LogOutIcon, PlusIcon } from "lucide-react";
|
||||
import { signOut } from "next-auth/react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -29,6 +15,20 @@ import { cn } from "@formbricks/lib/cn";
|
||||
import { capitalizeFirstLetter } from "@formbricks/lib/utils/strings";
|
||||
import { TOrganization } from "@formbricks/types/organizations";
|
||||
import { TUser } from "@formbricks/types/user";
|
||||
import { ProfileAvatar } from "@formbricks/ui/components/Avatars";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@formbricks/ui/components/DropdownMenu";
|
||||
|
||||
interface LandingSidebarProps {
|
||||
isMultiOrgEnabled: boolean;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { LandingSidebar } from "@/app/(app)/(onboarding)/organizations/[organizationId]/landing/components/landing-sidebar";
|
||||
import { getEnterpriseLicense } from "@/modules/ee/license-check/lib/utils";
|
||||
import { Header } from "@/modules/ui/components/header";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { getEnterpriseLicense } from "@formbricks/ee/lib/service";
|
||||
import { authOptions } from "@formbricks/lib/authOptions";
|
||||
import { getOrganization, getOrganizationsByUserId } from "@formbricks/lib/organization/service";
|
||||
import { getUser } from "@formbricks/lib/user/service";
|
||||
import { Header } from "@formbricks/ui/components/Header";
|
||||
|
||||
const Page = async (props) => {
|
||||
const params = await props.params;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { PosthogIdentify } from "@/app/(app)/environments/[environmentId]/components/PosthogIdentify";
|
||||
import { ToasterClient } from "@/modules/ui/components/toaster-client";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { redirect } from "next/navigation";
|
||||
@@ -8,6 +7,7 @@ import { canUserAccessOrganization } from "@formbricks/lib/organization/auth";
|
||||
import { getOrganization } from "@formbricks/lib/organization/service";
|
||||
import { getUser } from "@formbricks/lib/user/service";
|
||||
import { AuthorizationError } from "@formbricks/types/errors";
|
||||
import { ToasterClient } from "@formbricks/ui/components/ToasterClient";
|
||||
|
||||
const ProductOnboardingLayout = async (props) => {
|
||||
const params = await props.params;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { OnboardingOptionsContainer } from "@/app/(app)/(onboarding)/organizations/components/OnboardingOptionsContainer";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Header } from "@/modules/ui/components/header";
|
||||
import { GlobeIcon, GlobeLockIcon, LinkIcon, XIcon } from "lucide-react";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { redirect } from "next/navigation";
|
||||
import { authOptions } from "@formbricks/lib/authOptions";
|
||||
import { getUserProducts } from "@formbricks/lib/product/service";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Header } from "@formbricks/ui/components/Header";
|
||||
|
||||
interface ChannelPageProps {
|
||||
params: Promise<{
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { OnboardingOptionsContainer } from "@/app/(app)/(onboarding)/organizations/components/OnboardingOptionsContainer";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Header } from "@/modules/ui/components/header";
|
||||
import { HeartIcon, ListTodoIcon, XIcon } from "lucide-react";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { redirect } from "next/navigation";
|
||||
import { authOptions } from "@formbricks/lib/authOptions";
|
||||
import { getUserProducts } from "@formbricks/lib/product/service";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Header } from "@formbricks/ui/components/Header";
|
||||
|
||||
interface ModePageProps {
|
||||
params: Promise<{
|
||||
|
||||
@@ -4,20 +4,6 @@ import { createProductAction } from "@/app/(app)/environments/[environmentId]/ac
|
||||
import { getFormattedErrorMessage } from "@/lib/utils/helper";
|
||||
import { TOrganizationTeam } from "@/modules/ee/teams/product-teams/types/teams";
|
||||
import { CreateTeamModal } from "@/modules/ee/teams/team-list/components/create-team-modal";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { ColorPicker } from "@/modules/ui/components/color-picker";
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormError,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormProvider,
|
||||
} from "@/modules/ui/components/form";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { MultiSelect } from "@/modules/ui/components/multi-select";
|
||||
import { SurveyInline } from "@/modules/ui/components/survey";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useTranslations } from "next-intl";
|
||||
import Image from "next/image";
|
||||
@@ -34,6 +20,20 @@ import {
|
||||
TProductUpdateInput,
|
||||
ZProductUpdateInput,
|
||||
} from "@formbricks/types/product";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { ColorPicker } from "@formbricks/ui/components/ColorPicker";
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormError,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormProvider,
|
||||
} from "@formbricks/ui/components/Form";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { MultiSelect } from "@formbricks/ui/components/MultiSelect";
|
||||
import { SurveyInline } from "@formbricks/ui/components/Survey";
|
||||
|
||||
interface ProductSettingsProps {
|
||||
organizationId: string;
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { getTeamsByOrganizationId } from "@/app/(app)/(onboarding)/lib/onboarding";
|
||||
import { getCustomHeadline } from "@/app/(app)/(onboarding)/lib/utils";
|
||||
import { ProductSettings } from "@/app/(app)/(onboarding)/organizations/[organizationId]/products/new/settings/components/ProductSettings";
|
||||
import { getRoleManagementPermission } from "@/modules/ee/license-check/lib/utils";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Header } from "@/modules/ui/components/header";
|
||||
import { XIcon } from "lucide-react";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { redirect } from "next/navigation";
|
||||
import { getRoleManagementPermission } from "@formbricks/ee/lib/service";
|
||||
import { authOptions } from "@formbricks/lib/authOptions";
|
||||
import { DEFAULT_BRAND_COLOR, DEFAULT_LOCALE } from "@formbricks/lib/constants";
|
||||
import { getOrganization } from "@formbricks/lib/organization/service";
|
||||
import { getUserProducts } from "@formbricks/lib/product/service";
|
||||
import { getUserLocale } from "@formbricks/lib/user/service";
|
||||
import { TProductConfigChannel, TProductConfigIndustry, TProductMode } from "@formbricks/types/product";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Header } from "@formbricks/ui/components/Header";
|
||||
|
||||
interface ProductSettingsPageProps {
|
||||
params: Promise<{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { OptionCard } from "@/modules/ui/components/option-card";
|
||||
import { LucideProps } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { ForwardRefExoticComponent, RefAttributes } from "react";
|
||||
import { OptionCard } from "@formbricks/ui/components/OptionCard";
|
||||
|
||||
interface OnboardingOptionsContainerProps {
|
||||
options: {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { FormbricksClient } from "@/app/(app)/components/FormbricksClient";
|
||||
import { PosthogIdentify } from "@/app/(app)/environments/[environmentId]/components/PosthogIdentify";
|
||||
import { ResponseFilterProvider } from "@/app/(app)/environments/[environmentId]/components/ResponseFilterContext";
|
||||
import { DevEnvironmentBanner } from "@/modules/ui/components/dev-environment-banner";
|
||||
import { ToasterClient } from "@/modules/ui/components/toaster-client";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { redirect } from "next/navigation";
|
||||
@@ -12,6 +10,8 @@ import { getEnvironment } from "@formbricks/lib/environment/service";
|
||||
import { getOrganizationByEnvironmentId } from "@formbricks/lib/organization/service";
|
||||
import { getUser } from "@formbricks/lib/user/service";
|
||||
import { AuthorizationError } from "@formbricks/types/errors";
|
||||
import { DevEnvironmentBanner } from "@formbricks/ui/components/DevEnvironmentBanner";
|
||||
import { ToasterClient } from "@formbricks/ui/components/ToasterClient";
|
||||
|
||||
const SurveyEditorEnvironmentLayout = async (props) => {
|
||||
const params = await props.params;
|
||||
|
||||
@@ -12,12 +12,9 @@ import {
|
||||
getProductIdFromSurveyId,
|
||||
} from "@/lib/utils/helper";
|
||||
import { getSegment, getSurvey } from "@/lib/utils/services";
|
||||
import { getSurveyFollowUpsPermission } from "@/modules/ee/license-check/lib/utils";
|
||||
import { checkMultiLanguagePermission } from "@/modules/ee/multi-language-surveys/lib/actions";
|
||||
import { z } from "zod";
|
||||
import { createActionClass } from "@formbricks/lib/actionClass/service";
|
||||
import { UNSPLASH_ACCESS_KEY, UNSPLASH_ALLOWED_DOMAINS } from "@formbricks/lib/constants";
|
||||
import { getOrganization } from "@formbricks/lib/organization/service";
|
||||
import { getProduct } from "@formbricks/lib/product/service";
|
||||
import {
|
||||
cloneSegment,
|
||||
@@ -29,37 +26,15 @@ import { surveyCache } from "@formbricks/lib/survey/cache";
|
||||
import { loadNewSegmentInSurvey, updateSurvey } from "@formbricks/lib/survey/service";
|
||||
import { ZActionClassInput } from "@formbricks/types/action-classes";
|
||||
import { ZId } from "@formbricks/types/common";
|
||||
import { OperationNotAllowedError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { ZBaseFilters, ZSegmentFilters, ZSegmentUpdateInput } from "@formbricks/types/segment";
|
||||
import { ZSurvey } from "@formbricks/types/surveys/types";
|
||||
|
||||
/**
|
||||
* Checks if survey follow-ups are enabled for the given organization.
|
||||
*
|
||||
* @param { string } organizationId The ID of the organization to check.
|
||||
* @returns { Promise<void> } A promise that resolves if the permission is granted.
|
||||
* @throws { ResourceNotFoundError } If the organization is not found.
|
||||
* @throws { OperationNotAllowedError } If survey follow-ups are not enabled for the organization.
|
||||
*/
|
||||
const checkSurveyFollowUpsPermission = async (organizationId: string): Promise<void> => {
|
||||
const organization = await getOrganization(organizationId);
|
||||
if (!organization) {
|
||||
throw new ResourceNotFoundError("Organization", organizationId);
|
||||
}
|
||||
|
||||
const isSurveyFollowUpsEnabled = await getSurveyFollowUpsPermission(organization);
|
||||
if (!isSurveyFollowUpsEnabled) {
|
||||
throw new OperationNotAllowedError("Survey follow ups are not enabled for this organization");
|
||||
}
|
||||
};
|
||||
|
||||
export const updateSurveyAction = authenticatedActionClient
|
||||
.schema(ZSurvey)
|
||||
.action(async ({ ctx, parsedInput }) => {
|
||||
const organizationId = await getOrganizationIdFromSurveyId(parsedInput.id);
|
||||
await checkAuthorizationUpdated({
|
||||
userId: ctx.user.id,
|
||||
organizationId,
|
||||
organizationId: await getOrganizationIdFromSurveyId(parsedInput.id),
|
||||
access: [
|
||||
{
|
||||
type: "organization",
|
||||
@@ -73,14 +48,6 @@ export const updateSurveyAction = authenticatedActionClient
|
||||
],
|
||||
});
|
||||
|
||||
if (parsedInput.followUps?.length) {
|
||||
await checkSurveyFollowUpsPermission(organizationId);
|
||||
}
|
||||
|
||||
if (parsedInput.languages?.length) {
|
||||
await checkMultiLanguagePermission(organizationId);
|
||||
}
|
||||
|
||||
return await updateSurvey(parsedInput);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { ModalWithTabs } from "@/modules/ui/components/modal-with-tabs";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { TActionClass } from "@formbricks/types/action-classes";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { ModalWithTabs } from "@formbricks/ui/components/ModalWithTabs";
|
||||
import { CreateNewActionTab } from "./CreateNewActionTab";
|
||||
import { SavedActionsTab } from "./SavedActionsTab";
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { QuestionToggleTable } from "@/modules/ui/components/question-toggle-table";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -11,6 +9,8 @@ import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/uti
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyAddressQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { QuestionToggleTable } from "@formbricks/ui/components/QuestionToggleTable";
|
||||
|
||||
interface AddressQuestionFormProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { Badge } from "@/modules/ui/components/badge";
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel } from "@/modules/ui/components/form";
|
||||
import { Slider } from "@/modules/ui/components/slider";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { CheckIcon } from "lucide-react";
|
||||
@@ -11,6 +8,9 @@ import { UseFormReturn } from "react-hook-form";
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { TProductStyling } from "@formbricks/types/product";
|
||||
import { TSurveyStyling } from "@formbricks/types/surveys/types";
|
||||
import { Badge } from "@formbricks/ui/components/Badge";
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel } from "@formbricks/ui/components/Form";
|
||||
import { Slider } from "@formbricks/ui/components/Slider";
|
||||
import { SurveyBgSelectorTab } from "./SurveyBgSelectorTab";
|
||||
|
||||
interface BackgroundStylingCardProps {
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
import { LocalizedEditor } from "@/modules/ee/multi-language-surveys/components/localized-editor";
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { OptionsSwitch } from "@/modules/ui/components/options-switch";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { type JSX, useState } from "react";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyCTAQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { OptionsSwitch } from "@formbricks/ui/components/OptionsSwitch";
|
||||
|
||||
const options = [
|
||||
{
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { AdvancedOptionToggle } from "@/modules/ui/components/advanced-option-toggle";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { type JSX, useEffect, useState } from "react";
|
||||
@@ -10,6 +6,10 @@ import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/uti
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyCalQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { AdvancedOptionToggle } from "@formbricks/ui/components/AdvancedOptionToggle";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
|
||||
interface CalQuestionFormProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { Badge } from "@/modules/ui/components/badge";
|
||||
import { CardArrangementTabs } from "@/modules/ui/components/card-arrangement-tabs";
|
||||
import { ColorPicker } from "@/modules/ui/components/color-picker";
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel } from "@/modules/ui/components/form";
|
||||
import { Slider } from "@/modules/ui/components/slider";
|
||||
import { Switch } from "@/modules/ui/components/switch";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { CheckIcon } from "lucide-react";
|
||||
@@ -16,6 +10,12 @@ import { cn } from "@formbricks/lib/cn";
|
||||
import { COLOR_DEFAULTS } from "@formbricks/lib/styling/constants";
|
||||
import { TProduct, TProductStyling } from "@formbricks/types/product";
|
||||
import { TSurveyStyling, TSurveyType } from "@formbricks/types/surveys/types";
|
||||
import { Badge } from "@formbricks/ui/components/Badge";
|
||||
import { CardArrangementTabs } from "@formbricks/ui/components/CardArrangementTabs";
|
||||
import { ColorPicker } from "@formbricks/ui/components/ColorPicker";
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel } from "@formbricks/ui/components/Form";
|
||||
import { Slider } from "@formbricks/ui/components/Slider";
|
||||
import { Switch } from "@formbricks/ui/components/Switch";
|
||||
|
||||
type CardStylingSettingsProps = {
|
||||
open: boolean;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ColorPicker } from "@/modules/ui/components/color-picker";
|
||||
import { useState } from "react";
|
||||
import { ColorPicker } from "@formbricks/ui/components/ColorPicker";
|
||||
|
||||
interface ColorSurveyBgProps {
|
||||
handleBgChange: (bg: string, bgType: string) => void;
|
||||
|
||||
@@ -3,14 +3,6 @@ import {
|
||||
getDefaultOperatorForQuestion,
|
||||
replaceEndingCardHeadlineRecall,
|
||||
} from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/modules/ui/components/dropdown-menu";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import {
|
||||
@@ -28,6 +20,14 @@ import { duplicateLogicItem } from "@formbricks/lib/surveyLogic/utils";
|
||||
import { replaceHeadlineRecall } from "@formbricks/lib/utils/recall";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyLogic, TSurveyQuestion } from "@formbricks/types/surveys/types";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@formbricks/ui/components/DropdownMenu";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
|
||||
interface ConditionalLogicProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
import { LocalizedEditor } from "@/modules/ee/multi-language-surveys/components/localized-editor";
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { type JSX, useState } from "react";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyConsentQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
|
||||
interface ConsentQuestionFormProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { QuestionToggleTable } from "@/modules/ui/components/question-toggle-table";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -11,6 +9,8 @@ import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/uti
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyContactInfoQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { QuestionToggleTable } from "@formbricks/ui/components/QuestionToggleTable";
|
||||
|
||||
interface ContactInfoQuestionFormProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
import { isValidCssSelector } from "@/app/lib/actionClass/actionClass";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { CodeActionForm } from "@/modules/ui/components/code-action-form";
|
||||
import { FormControl, FormError, FormField, FormItem, FormLabel } from "@/modules/ui/components/form";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { NoCodeActionForm } from "@/modules/ui/components/no-code-action-form";
|
||||
import { TabToggle } from "@/modules/ui/components/tab-toggle";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useMemo } from "react";
|
||||
@@ -19,6 +12,13 @@ import {
|
||||
ZActionClassInput,
|
||||
} from "@formbricks/types/action-classes";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { FormControl, FormError, FormField, FormItem, FormLabel } from "@formbricks/ui/components/Form";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { TabToggle } from "@formbricks/ui/components/TabToggle";
|
||||
import { CodeActionForm } from "@formbricks/ui/components/organisms/CodeActionForm";
|
||||
import { NoCodeActionForm } from "@formbricks/ui/components/organisms/NoCodeActionForm";
|
||||
import { createActionClassAction } from "../actions";
|
||||
|
||||
interface CreateNewActionTabProps {
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { OptionsSwitch } from "@/modules/ui/components/options-switch";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -10,6 +7,9 @@ import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/uti
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyDateQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { OptionsSwitch } from "@formbricks/ui/components/OptionsSwitch";
|
||||
|
||||
interface IDateQuestionFormProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -7,16 +7,12 @@ import {
|
||||
findEndingCardUsedInLogic,
|
||||
formatTextWithSlashes,
|
||||
} from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import { ConfirmationModal } from "@/modules/ui/components/confirmation-modal";
|
||||
import { OptionsSwitch } from "@/modules/ui/components/options-switch";
|
||||
import { TooltipRenderer } from "@/modules/ui/components/tooltip";
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { GripIcon, Handshake, Undo2 } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { recallToHeadline } from "@formbricks/lib/utils/recall";
|
||||
@@ -29,6 +25,8 @@ import {
|
||||
TSurveyRedirectUrlCard,
|
||||
} from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { OptionsSwitch } from "@formbricks/ui/components/OptionsSwitch";
|
||||
import { TooltipRenderer } from "@formbricks/ui/components/Tooltip";
|
||||
|
||||
interface EditEndingCardProps {
|
||||
localSurvey: TSurvey;
|
||||
@@ -67,8 +65,6 @@ export const EditEndingCard = ({
|
||||
? plan === "free" && endingCard.type !== "redirectToUrl"
|
||||
: false;
|
||||
|
||||
const [openDeleteConfirmationModal, setOpenDeleteConfirmationModal] = useState(false);
|
||||
|
||||
const endingCardTypes = [
|
||||
{ value: "endScreen", label: t("environments.surveys.edit.ending_card") },
|
||||
{
|
||||
@@ -81,7 +77,6 @@ export const EditEndingCard = ({
|
||||
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
||||
id: endingCard.id,
|
||||
});
|
||||
|
||||
let open = activeQuestionId === endingCard.id;
|
||||
|
||||
const setOpen = (e) => {
|
||||
@@ -102,16 +97,6 @@ export const EditEndingCard = ({
|
||||
};
|
||||
|
||||
const deleteEndingCard = () => {
|
||||
const isEndingCardUsedInFollowUps = localSurvey.followUps.some((followUp) => {
|
||||
if (followUp.trigger.type === "endings") {
|
||||
if (followUp.trigger.properties?.endingIds?.includes(endingCard.id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// checking if this ending card is used in logic
|
||||
const quesIdx = findEndingCardUsedInLogic(localSurvey, endingCard.id);
|
||||
|
||||
@@ -120,11 +105,6 @@ export const EditEndingCard = ({
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEndingCardUsedInFollowUps) {
|
||||
setOpenDeleteConfirmationModal(true);
|
||||
return;
|
||||
}
|
||||
|
||||
setLocalSurvey((prevSurvey) => {
|
||||
const updatedEndings = prevSurvey.endings.filter((_, index) => index !== endingCardIndex);
|
||||
return { ...prevSurvey, endings: updatedEndings };
|
||||
@@ -285,37 +265,6 @@ export const EditEndingCard = ({
|
||||
)}
|
||||
</Collapsible.CollapsibleContent>
|
||||
</Collapsible.Root>
|
||||
|
||||
<ConfirmationModal
|
||||
buttonText={t("common.delete")}
|
||||
onConfirm={() => {
|
||||
setLocalSurvey((prevSurvey) => {
|
||||
const updatedEndings = prevSurvey.endings.filter((_, index) => index !== endingCardIndex);
|
||||
const surveyFollowUps = prevSurvey.followUps.map((f) => {
|
||||
if (f.trigger.properties?.endingIds?.includes(endingCard.id)) {
|
||||
return {
|
||||
...f,
|
||||
trigger: {
|
||||
...f.trigger,
|
||||
properties: {
|
||||
...f.trigger.properties,
|
||||
endingIds: f.trigger.properties.endingIds.filter((id) => id !== endingCard.id),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return f;
|
||||
});
|
||||
|
||||
return { ...prevSurvey, endings: updatedEndings, followUps: surveyFollowUps };
|
||||
});
|
||||
}}
|
||||
open={openDeleteConfirmationModal}
|
||||
setOpen={setOpenDeleteConfirmationModal}
|
||||
text={t("environments.surveys.edit.follow_ups_ending_card_delete_modal_text")}
|
||||
title={t("environments.surveys.edit.follow_ups_ending_card_delete_modal_title")}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
import { LocalizedEditor } from "@/modules/ee/multi-language-surveys/components/localized-editor";
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { FileInput } from "@/modules/ui/components/file-input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { Switch } from "@/modules/ui/components/switch";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { Hand } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -14,6 +11,9 @@ import { cn } from "@formbricks/lib/cn";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyQuestionId, TSurveyWelcomeCard } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { FileInput } from "@formbricks/ui/components/FileInput";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { Switch } from "@formbricks/ui/components/Switch";
|
||||
|
||||
interface EditWelcomeCardProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { ConfirmationModal } from "@/modules/ui/components/confirmation-modal";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/modules/ui/components/dropdown-menu";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { ArrowDownIcon, ArrowUpIcon, CopyIcon, EllipsisIcon, TrashIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -29,6 +19,16 @@ import {
|
||||
TSurveyQuestionTypeEnum,
|
||||
TSurveyRedirectUrlCard,
|
||||
} from "@formbricks/types/surveys/types";
|
||||
import { ConfirmationModal } from "@formbricks/ui/components/ConfirmationModal";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@formbricks/ui/components/DropdownMenu";
|
||||
|
||||
interface EditorCardMenuProps {
|
||||
survey: TSurvey;
|
||||
@@ -184,6 +184,7 @@ export const EditorCardMenu = ({
|
||||
deleteCard(cardIdx);
|
||||
}}
|
||||
/>
|
||||
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<EllipsisIcon className="h-4 w-4 text-slate-500 hover:text-slate-600" />
|
||||
@@ -285,6 +286,7 @@ export const EditorCardMenu = ({
|
||||
</div>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
<ConfirmationModal
|
||||
open={logicWarningModal}
|
||||
setOpen={setLogicWarningModal}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
"use client";
|
||||
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { Switch } from "@/modules/ui/components/switch";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useState } from "react";
|
||||
import { getLocalizedValue } from "@formbricks/lib/i18n/utils";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyEndScreenCard } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { Switch } from "@formbricks/ui/components/Switch";
|
||||
|
||||
interface EndScreenFormProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { AdvancedOptionToggle } from "@/modules/ui/components/advanced-option-toggle";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { useGetBillingInfo } from "@/modules/utils/hooks/useGetBillingInfo";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon, XCircleIcon } from "lucide-react";
|
||||
@@ -18,6 +15,9 @@ import { TAllowedFileExtension, ZAllowedFileExtension } from "@formbricks/types/
|
||||
import { TProduct } from "@formbricks/types/product";
|
||||
import { TSurvey, TSurveyFileUploadQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { AdvancedOptionToggle } from "@formbricks/ui/components/AdvancedOptionToggle";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
|
||||
interface FileUploadFormProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { ColorPicker } from "@/modules/ui/components/color-picker";
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel } from "@/modules/ui/components/form";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { CheckIcon, SparklesIcon } from "lucide-react";
|
||||
@@ -14,6 +11,9 @@ import { COLOR_DEFAULTS } from "@formbricks/lib/styling/constants";
|
||||
import { mixColor } from "@formbricks/lib/utils/colors";
|
||||
import { TProductStyling } from "@formbricks/types/product";
|
||||
import { TSurveyStyling } from "@formbricks/types/surveys/types";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { ColorPicker } from "@formbricks/ui/components/ColorPicker";
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel } from "@formbricks/ui/components/Form";
|
||||
|
||||
type FormStylingSettingsProps = {
|
||||
open: boolean;
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { findHiddenFieldUsedInLogic } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { Switch } from "@/modules/ui/components/switch";
|
||||
import { Tag } from "@/modules/ui/components/tag";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { EyeOff } from "lucide-react";
|
||||
@@ -16,6 +11,11 @@ import { cn } from "@formbricks/lib/cn";
|
||||
import { extractRecallInfo } from "@formbricks/lib/utils/recall";
|
||||
import { TSurvey, TSurveyHiddenFields, TSurveyQuestionId } from "@formbricks/types/surveys/types";
|
||||
import { validateId } from "@formbricks/types/surveys/validation";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { Switch } from "@formbricks/ui/components/Switch";
|
||||
import { Tag } from "@formbricks/ui/components/Tag";
|
||||
|
||||
interface HiddenFieldsCardProps {
|
||||
localSurvey: TSurvey;
|
||||
@@ -84,17 +84,6 @@ export const HiddenFieldsCard = ({
|
||||
return;
|
||||
}
|
||||
|
||||
const isHiddenFieldUsedInFollowUp = localSurvey.followUps
|
||||
.filter((f) => !f.deleted)
|
||||
.some((followUp) => {
|
||||
return followUp.action.properties.to === fieldId;
|
||||
});
|
||||
|
||||
if (isHiddenFieldUsedInFollowUp) {
|
||||
toast.error(t("environments.surveys.edit.follow_ups_hidden_field_error"));
|
||||
return;
|
||||
}
|
||||
|
||||
updateSurvey(
|
||||
{
|
||||
enabled: true,
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { Badge } from "@/modules/ui/components/badge";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { RadioGroup, RadioGroupItem } from "@/modules/ui/components/radio-group";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { AlertCircleIcon, CheckIcon, LinkIcon, MonitorIcon } from "lucide-react";
|
||||
@@ -14,6 +11,9 @@ import { getDefaultEndingCard } from "@formbricks/lib/templates";
|
||||
import { TEnvironment } from "@formbricks/types/environment";
|
||||
import { TSegment } from "@formbricks/types/segment";
|
||||
import { TSurvey, TSurveyType } from "@formbricks/types/surveys/types";
|
||||
import { Badge } from "@formbricks/ui/components/Badge";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { RadioGroup, RadioGroupItem } from "@formbricks/ui/components/RadioGroup";
|
||||
|
||||
interface HowToSendCardProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FileInput } from "@/modules/ui/components/file-input";
|
||||
import { FileInput } from "@formbricks/ui/components/FileInput";
|
||||
|
||||
interface UploadImageSurveyBgProps {
|
||||
environmentId: string;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { LogicEditorActions } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/components/LogicEditorActions";
|
||||
import { LogicEditorConditions } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/components/LogicEditorConditions";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/modules/ui/components/select";
|
||||
import { ArrowRightIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { ReactElement, useMemo } from "react";
|
||||
import { getLocalizedValue } from "@formbricks/lib/i18n/utils";
|
||||
import { QUESTIONS_ICON_MAP } from "@formbricks/lib/utils/questions";
|
||||
import { TSurvey, TSurveyLogic, TSurveyQuestion } from "@formbricks/types/surveys/types";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@formbricks/ui/components/Select";
|
||||
|
||||
interface LogicEditorProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -4,15 +4,7 @@ import {
|
||||
getActionTargetOptions,
|
||||
getActionValueOptions,
|
||||
getActionVariableOptions,
|
||||
hasJumpToQuestionAction,
|
||||
} from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/modules/ui/components/dropdown-menu";
|
||||
import { InputCombobox } from "@/modules/ui/components/input-combo-box";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { CopyIcon, CornerDownRightIcon, EllipsisVerticalIcon, PlusIcon, TrashIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -27,6 +19,13 @@ import {
|
||||
TSurveyLogicAction,
|
||||
TSurveyQuestion,
|
||||
} from "@formbricks/types/surveys/types";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@formbricks/ui/components/DropdownMenu";
|
||||
import { InputCombobox } from "@formbricks/ui/components/InputCombobox";
|
||||
|
||||
interface LogicEditorActions {
|
||||
localSurvey: TSurvey;
|
||||
@@ -61,11 +60,7 @@ export function LogicEditorActions({
|
||||
actionsClone.splice(actionIdx, 1);
|
||||
break;
|
||||
case "addBelow":
|
||||
actionsClone.splice(actionIdx + 1, 0, {
|
||||
id: createId(),
|
||||
objective: hasJumpToQuestionAction(logicItem.actions) ? "requireAnswer" : "jumpToQuestion",
|
||||
target: "",
|
||||
});
|
||||
actionsClone.splice(actionIdx + 1, 0, { id: createId(), objective: "jumpToQuestion", target: "" });
|
||||
break;
|
||||
case "duplicate":
|
||||
actionsClone.splice(actionIdx + 1, 0, { ...actionsClone[actionIdx], id: createId() });
|
||||
@@ -93,11 +88,6 @@ export function LogicEditorActions({
|
||||
handleActionsChange("update", actionIdx, actionBody);
|
||||
};
|
||||
|
||||
const filteredObjectiveOptions = actionObjectiveOptions.filter(
|
||||
(option) => option.value !== "jumpToQuestion"
|
||||
);
|
||||
const jumpToQuestionActionIdx = actions.findIndex((action) => action.objective === "jumpToQuestion");
|
||||
|
||||
return (
|
||||
<div className="flex grow gap-2">
|
||||
<CornerDownRightIcon className="mt-3 h-4 w-4 shrink-0" />
|
||||
@@ -112,11 +102,7 @@ export function LogicEditorActions({
|
||||
id={`action-${idx}-objective`}
|
||||
key={`objective-${action.id}`}
|
||||
showSearch={false}
|
||||
options={
|
||||
jumpToQuestionActionIdx === -1 || idx === jumpToQuestionActionIdx
|
||||
? actionObjectiveOptions
|
||||
: filteredObjectiveOptions
|
||||
}
|
||||
options={actionObjectiveOptions}
|
||||
value={action.objective}
|
||||
onChangeValue={(val: TActionObjective) => {
|
||||
handleObjectiveChange(idx, val);
|
||||
|
||||
@@ -4,13 +4,6 @@ import {
|
||||
getDefaultOperatorForQuestion,
|
||||
getMatchValueProps,
|
||||
} from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/modules/ui/components/dropdown-menu";
|
||||
import { InputCombobox, TComboboxOption } from "@/modules/ui/components/input-combo-box";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { CopyIcon, EllipsisVerticalIcon, PlusIcon, TrashIcon, WorkflowIcon } from "lucide-react";
|
||||
@@ -34,6 +27,13 @@ import {
|
||||
TSurveyLogicConditionsOperator,
|
||||
TSurveyQuestion,
|
||||
} from "@formbricks/types/surveys/types";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@formbricks/ui/components/DropdownMenu";
|
||||
import { InputCombobox, TComboboxOption } from "@formbricks/ui/components/InputCombobox";
|
||||
|
||||
interface LogicEditorConditionsProps {
|
||||
conditions: TConditionGroup;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { ShuffleOptionSelect } from "@/modules/ui/components/shuffle-option-select";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon, TrashIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -12,6 +9,9 @@ import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/uti
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TI18nString, TSurvey, TSurveyMatrixQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { ShuffleOptionSelect } from "@formbricks/ui/components/ShuffleOptionSelect";
|
||||
import { isLabelValidForAllLanguages } from "../lib/validation";
|
||||
|
||||
interface MatrixQuestionFormProps {
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
import { findOptionUsedInLogic } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { ShuffleOptionSelect } from "@/modules/ui/components/shuffle-option-select";
|
||||
import { DndContext } from "@dnd-kit/core";
|
||||
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
@@ -23,6 +20,9 @@ import {
|
||||
TSurveyQuestionTypeEnum,
|
||||
} from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { ShuffleOptionSelect } from "@formbricks/ui/components/ShuffleOptionSelect";
|
||||
import { QuestionOptionChoice } from "./QuestionOptionChoice";
|
||||
|
||||
interface MultipleChoiceQuestionFormProps {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { AdvancedOptionToggle } from "@/modules/ui/components/advanced-option-toggle";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -11,6 +9,8 @@ import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/uti
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyNPSQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { AdvancedOptionToggle } from "@formbricks/ui/components/AdvancedOptionToggle";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
|
||||
interface NPSQuestionFormProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { OptionsSwitch } from "@/modules/ui/components/options-switch";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { HashIcon, LinkIcon, MailIcon, MessageSquareTextIcon, PhoneIcon, PlusIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -16,6 +13,9 @@ import {
|
||||
TSurveyOpenTextQuestionInputType,
|
||||
} from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { OptionsSwitch } from "@formbricks/ui/components/OptionsSwitch";
|
||||
|
||||
const questionTypes = [
|
||||
{ value: "text", label: "common.text", icon: <MessageSquareTextIcon className="h-4 w-4" /> },
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { FileInput } from "@/modules/ui/components/file-input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { Switch } from "@/modules/ui/components/switch";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
@@ -13,6 +9,10 @@ import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/uti
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyPictureSelectionQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { FileInput } from "@formbricks/ui/components/FileInput";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { Switch } from "@formbricks/ui/components/Switch";
|
||||
|
||||
interface PictureSelectionFormProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { getPlacementStyle } from "@/modules/ui/components/preview-survey/lib/utils";
|
||||
import { RadioGroup, RadioGroupItem } from "@/modules/ui/components/radio-group";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { TPlacement } from "@formbricks/types/common";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { getPlacementStyle } from "@formbricks/ui/components/PreviewSurvey/lib/utils";
|
||||
import { RadioGroup, RadioGroupItem } from "@formbricks/ui/components/RadioGroup";
|
||||
|
||||
const placements = [
|
||||
{ name: "common.bottom_right", value: "bottomRight", disabled: false },
|
||||
|
||||
@@ -4,8 +4,6 @@ import { ContactInfoQuestionForm } from "@/app/(app)/(survey-editor)/environment
|
||||
import { RankingQuestionForm } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/components/RankingQuestionForm";
|
||||
import { formatTextWithSlashes } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { Switch } from "@/modules/ui/components/switch";
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
@@ -26,6 +24,8 @@ import {
|
||||
TSurveyQuestionTypeEnum,
|
||||
} from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { Switch } from "@formbricks/ui/components/Switch";
|
||||
import { AddressQuestionForm } from "./AddressQuestionForm";
|
||||
import { AdvancedSettings } from "./AdvancedSettings";
|
||||
import { CTAQuestionForm } from "./CTAQuestionForm";
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ProBadge } from "@/modules/ui/components/pro-badge";
|
||||
import { MailIcon, PaintbrushIcon, Rows3Icon, SettingsIcon } from "lucide-react";
|
||||
import { PaintbrushIcon, Rows3Icon, SettingsIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { type JSX, useMemo } from "react";
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
@@ -9,15 +8,31 @@ interface Tab {
|
||||
id: TSurveyEditorTabs;
|
||||
label: string;
|
||||
icon: JSX.Element;
|
||||
isPro?: boolean;
|
||||
}
|
||||
|
||||
const tabs: Tab[] = [
|
||||
{
|
||||
id: "questions",
|
||||
label: "common.questions",
|
||||
icon: <Rows3Icon className="h-5 w-5" />,
|
||||
},
|
||||
{
|
||||
id: "styling",
|
||||
label: "common.styling",
|
||||
icon: <PaintbrushIcon className="h-5 w-5" />,
|
||||
},
|
||||
{
|
||||
id: "settings",
|
||||
label: "common.settings",
|
||||
icon: <SettingsIcon className="h-5 w-5" />,
|
||||
},
|
||||
];
|
||||
|
||||
interface QuestionsAudienceTabsProps {
|
||||
activeId: TSurveyEditorTabs;
|
||||
setActiveId: React.Dispatch<React.SetStateAction<TSurveyEditorTabs>>;
|
||||
isStylingTabVisible?: boolean;
|
||||
isCxMode: boolean;
|
||||
isSurveyFollowUpsAllowed: boolean;
|
||||
}
|
||||
|
||||
export const QuestionsAudienceTabs = ({
|
||||
@@ -25,35 +40,7 @@ export const QuestionsAudienceTabs = ({
|
||||
setActiveId,
|
||||
isStylingTabVisible,
|
||||
isCxMode,
|
||||
isSurveyFollowUpsAllowed = false,
|
||||
}: QuestionsAudienceTabsProps) => {
|
||||
const tabs: Tab[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
id: "questions",
|
||||
label: "common.questions",
|
||||
icon: <Rows3Icon className="h-5 w-5" />,
|
||||
},
|
||||
{
|
||||
id: "styling",
|
||||
label: "common.styling",
|
||||
icon: <PaintbrushIcon className="h-5 w-5" />,
|
||||
},
|
||||
{
|
||||
id: "settings",
|
||||
label: "common.settings",
|
||||
icon: <SettingsIcon className="h-5 w-5" />,
|
||||
},
|
||||
{
|
||||
id: "followUps",
|
||||
label: "environments.surveys.edit.follow_ups",
|
||||
icon: <MailIcon className="h-5 w-5" />,
|
||||
isPro: !isSurveyFollowUpsAllowed,
|
||||
},
|
||||
],
|
||||
[isSurveyFollowUpsAllowed]
|
||||
);
|
||||
|
||||
const t = useTranslations();
|
||||
const tabsComputed = useMemo(() => {
|
||||
if (isStylingTabVisible) {
|
||||
@@ -82,7 +69,6 @@ export const QuestionsAudienceTabs = ({
|
||||
aria-current={tab.id === activeId ? "page" : undefined}>
|
||||
{tab.icon && <div className="mr-2 h-5 w-5">{tab.icon}</div>}
|
||||
{t(tab.label)}
|
||||
{tab.isPro && <ProBadge />}
|
||||
</button>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
@@ -282,13 +282,11 @@ export const QuestionsView = ({
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updatedSurvey.questions.splice(questionIdx, 1);
|
||||
|
||||
const firstEndingCard = localSurvey.endings[0];
|
||||
setLocalSurvey(updatedSurvey);
|
||||
delete internalQuestionIdMap[questionId];
|
||||
|
||||
if (questionId === activeQuestionIdTemp) {
|
||||
if (questionIdx <= localSurvey.questions.length && localSurvey.questions.length > 0) {
|
||||
setActiveQuestionId(localSurvey.questions[questionIdx % localSurvey.questions.length].id);
|
||||
@@ -296,7 +294,6 @@ export const QuestionsView = ({
|
||||
setActiveQuestionId(firstEndingCard.id);
|
||||
}
|
||||
}
|
||||
|
||||
toast.success(t("environments.surveys.edit.question_deleted"));
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { ShuffleOptionSelect } from "@/modules/ui/components/shuffle-option-select";
|
||||
import { DndContext } from "@dnd-kit/core";
|
||||
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
@@ -15,6 +12,9 @@ import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/uti
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TI18nString, TSurvey, TSurveyRankingQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { ShuffleOptionSelect } from "@formbricks/ui/components/ShuffleOptionSelect";
|
||||
import { QuestionOptionChoice } from "./QuestionOptionChoice";
|
||||
|
||||
interface RankingQuestionFormProps {
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import { QuestionFormInput } from "@/modules/surveys/components/QuestionFormInput";
|
||||
import { AdvancedOptionToggle } from "@/modules/ui/components/advanced-option-toggle";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { HashIcon, PlusIcon, SmileIcon, StarIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -9,6 +6,9 @@ import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/uti
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TSurvey, TSurveyRatingQuestion } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { AdvancedOptionToggle } from "@formbricks/ui/components/AdvancedOptionToggle";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { Dropdown } from "./RatingTypeDropdown";
|
||||
|
||||
interface RatingQuestionFormProps {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { AdvancedOptionToggle } from "@/modules/ui/components/advanced-option-toggle";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { RadioGroup, RadioGroupItem } from "@/modules/ui/components/radio-group";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { CheckIcon } from "lucide-react";
|
||||
@@ -11,6 +7,10 @@ import { useTranslations } from "next-intl";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { AdvancedOptionToggle } from "@formbricks/ui/components/AdvancedOptionToggle";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { RadioGroup, RadioGroupItem } from "@formbricks/ui/components/RadioGroup";
|
||||
|
||||
interface DisplayOption {
|
||||
id: "displayOnce" | "displayMultiple" | "respondMultiple" | "displaySome";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { TSurveyRedirectUrlCard } from "@formbricks/types/surveys/types";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
|
||||
interface RedirectUrlFormProps {
|
||||
endingCard: TSurveyRedirectUrlCard;
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { AdvancedOptionToggle } from "@/modules/ui/components/advanced-option-toggle";
|
||||
import { DatePicker } from "@/modules/ui/components/date-picker";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { Switch } from "@/modules/ui/components/switch";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { ArrowUpRight, CheckIcon } from "lucide-react";
|
||||
@@ -14,6 +9,11 @@ import { KeyboardEventHandler, useEffect, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { AdvancedOptionToggle } from "@formbricks/ui/components/AdvancedOptionToggle";
|
||||
import { DatePicker } from "@formbricks/ui/components/DatePicker";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { Switch } from "@formbricks/ui/components/Switch";
|
||||
|
||||
interface ResponseOptionsCardProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Code2Icon, MousePointerClickIcon, SparklesIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useState } from "react";
|
||||
import { TActionClass } from "@formbricks/types/action-classes";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
|
||||
interface SavedActionsTabProps {
|
||||
actionClasses: TActionClass[];
|
||||
|
||||
@@ -1,14 +1,3 @@
|
||||
import { AlertDialog } from "@/modules/ui/components/alert-dialog";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormProvider,
|
||||
} from "@/modules/ui/components/form";
|
||||
import { Switch } from "@/modules/ui/components/switch";
|
||||
import { RotateCcwIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import Link from "next/link";
|
||||
@@ -18,6 +7,17 @@ import toast from "react-hot-toast";
|
||||
import { TEnvironment } from "@formbricks/types/environment";
|
||||
import { TProduct, TProductStyling } from "@formbricks/types/product";
|
||||
import { TSurvey, TSurveyStyling } from "@formbricks/types/surveys/types";
|
||||
import { AlertDialog } from "@formbricks/ui/components/AlertDialog";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormProvider,
|
||||
} from "@formbricks/ui/components/Form";
|
||||
import { Switch } from "@formbricks/ui/components/Switch";
|
||||
import { BackgroundStylingCard } from "./BackgroundStylingCard";
|
||||
import { CardStylingSettings } from "./CardStylingSettings";
|
||||
import { FormStylingSettings } from "./FormStylingSettings";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { TabBar } from "@/modules/ui/components/tab-bar";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useEffect, useState } from "react";
|
||||
import { TabBar } from "@formbricks/ui/components/TabBar";
|
||||
import { AnimatedSurveyBg } from "./AnimatedSurveyBg";
|
||||
import { ColorSurveyBg } from "./ColorSurveyBg";
|
||||
import { UploadImageSurveyBg } from "./ImageSurveyBg";
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { FollowUpsView } from "@/modules/ee/survey-follow-ups/components/follow-ups-view";
|
||||
import { TTeamPermission } from "@/modules/ee/teams/product-teams/types/teams";
|
||||
import { PreviewSurvey } from "@/modules/ui/components/preview-survey";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { extractLanguageCodes, getEnabledLanguages } from "@formbricks/lib/i18n/utils";
|
||||
import { structuredClone } from "@formbricks/lib/pollyfills/structuredClone";
|
||||
@@ -16,6 +14,7 @@ import { TProduct } from "@formbricks/types/product";
|
||||
import { TSegment } from "@formbricks/types/segment";
|
||||
import { TSurvey, TSurveyEditorTabs, TSurveyStyling } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { PreviewSurvey } from "@formbricks/ui/components/PreviewSurvey";
|
||||
import { refetchProductAction } from "../actions";
|
||||
import { LoadingSkeleton } from "./LoadingSkeleton";
|
||||
import { QuestionsAudienceTabs } from "./QuestionsStylingSettingsTabs";
|
||||
@@ -41,10 +40,7 @@ interface SurveyEditorProps {
|
||||
plan: TOrganizationBillingPlan;
|
||||
isCxMode: boolean;
|
||||
locale: TUserLocale;
|
||||
mailFrom: string;
|
||||
isSurveyFollowUpsAllowed: boolean;
|
||||
productPermission: TTeamPermission | null;
|
||||
userEmail: string;
|
||||
}
|
||||
|
||||
export const SurveyEditor = ({
|
||||
@@ -64,10 +60,7 @@ export const SurveyEditor = ({
|
||||
plan,
|
||||
isCxMode = false,
|
||||
locale,
|
||||
mailFrom,
|
||||
isSurveyFollowUpsAllowed = false,
|
||||
productPermission,
|
||||
userEmail,
|
||||
}: SurveyEditorProps) => {
|
||||
const [activeView, setActiveView] = useState<TSurveyEditorTabs>("questions");
|
||||
const [activeQuestionId, setActiveQuestionId] = useState<string | null>(null);
|
||||
@@ -168,7 +161,6 @@ export const SurveyEditor = ({
|
||||
setActiveId={setActiveView}
|
||||
isCxMode={isCxMode}
|
||||
isStylingTabVisible={!!product.styling.allowStyleOverwrite}
|
||||
isSurveyFollowUpsAllowed={isSurveyFollowUpsAllowed}
|
||||
/>
|
||||
|
||||
{activeView === "questions" && (
|
||||
@@ -223,18 +215,6 @@ export const SurveyEditor = ({
|
||||
productPermission={productPermission}
|
||||
/>
|
||||
)}
|
||||
|
||||
{activeView === "followUps" && (
|
||||
<FollowUpsView
|
||||
localSurvey={localSurvey}
|
||||
setLocalSurvey={setLocalSurvey}
|
||||
selectedLanguageCode={selectedLanguageCode}
|
||||
mailFrom={mailFrom}
|
||||
isSurveyFollowUpsAllowed={isSurveyFollowUpsAllowed}
|
||||
userEmail={userEmail}
|
||||
locale={locale}
|
||||
/>
|
||||
)}
|
||||
</main>
|
||||
|
||||
<aside className="group hidden flex-1 flex-shrink-0 items-center justify-center overflow-hidden border-l border-slate-200 bg-slate-100 shadow-inner md:flex md:flex-col">
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
import { SurveyStatusDropdown } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SurveyStatusDropdown";
|
||||
import { getFormattedErrorMessage } from "@/lib/utils/helper";
|
||||
import { createSegmentAction } from "@/modules/ee/advanced-targeting/lib/actions";
|
||||
import { AlertDialog } from "@/modules/ui/components/alert-dialog";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/modules/ui/components/tooltip";
|
||||
import { isEqual } from "lodash";
|
||||
import { AlertTriangleIcon, ArrowLeftIcon, SettingsIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -25,6 +21,10 @@ import {
|
||||
ZSurveyEndScreenCard,
|
||||
ZSurveyRedirectUrlCard,
|
||||
} from "@formbricks/types/surveys/types";
|
||||
import { AlertDialog } from "@formbricks/ui/components/AlertDialog";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@formbricks/ui/components/Tooltip";
|
||||
import { updateSurveyAction } from "../actions";
|
||||
import { isSurveyValid } from "../lib/validation";
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { Switch } from "@/modules/ui/components/switch";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { CheckIcon } from "lucide-react";
|
||||
@@ -10,6 +8,8 @@ import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import { TPlacement } from "@formbricks/types/common";
|
||||
import { TSurvey, TSurveyProductOverwrites } from "@formbricks/types/surveys/types";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import { Switch } from "@formbricks/ui/components/Switch";
|
||||
import { Placement } from "./Placement";
|
||||
|
||||
interface SurveyPlacementCardProps {
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { findVariableUsedInLogic } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { FormControl, FormField, FormItem, FormProvider } from "@/modules/ui/components/form";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/modules/ui/components/select";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { TrashIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -20,6 +9,17 @@ import { useForm } from "react-hook-form";
|
||||
import toast from "react-hot-toast";
|
||||
import { extractRecallInfo } from "@formbricks/lib/utils/recall";
|
||||
import { TSurvey, TSurveyVariable } from "@formbricks/types/surveys/types";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { FormControl, FormField, FormItem, FormProvider } from "@formbricks/ui/components/Form";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@formbricks/ui/components/Select";
|
||||
|
||||
interface SurveyVariablesCardItemProps {
|
||||
variable?: TSurveyVariable;
|
||||
|
||||
@@ -1,16 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { getFormattedErrorMessage } from "@/lib/utils/helper";
|
||||
import { Alert, AlertDescription } from "@/modules/ui/components/alert";
|
||||
import { AlertDialog } from "@/modules/ui/components/alert-dialog";
|
||||
import { BasicAddFilterModal } from "@/modules/ui/components/basic-add-filter-modal";
|
||||
import { BasicSegmentEditor } from "@/modules/ui/components/basic-segment-editor";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { LoadSegmentModal } from "@/modules/ui/components/load-segment-modal";
|
||||
import { SaveAsNewSegmentModal } from "@/modules/ui/components/save-as-new-segment-modal";
|
||||
import { SegmentTitle } from "@/modules/ui/components/segment-title";
|
||||
import { TargetingIndicator } from "@/modules/ui/components/targeting-indicator";
|
||||
import { UpgradePlanNotice } from "@/modules/ui/components/upgrade-plan-notice";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { AlertCircle, CheckIcon, ChevronDownIcon, ChevronUpIcon, PencilIcon } from "lucide-react";
|
||||
@@ -25,6 +15,16 @@ import { isAdvancedSegment } from "@formbricks/lib/segment/utils";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TBaseFilter, TSegment, TSegmentCreateInput, TSegmentUpdateInput } from "@formbricks/types/segment";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { Alert, AlertDescription } from "@formbricks/ui/components/Alert";
|
||||
import { AlertDialog } from "@formbricks/ui/components/AlertDialog";
|
||||
import { BasicAddFilterModal } from "@formbricks/ui/components/BasicAddFilterModal";
|
||||
import { BasicSegmentEditor } from "@formbricks/ui/components/BasicSegmentEditor";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { LoadSegmentModal } from "@formbricks/ui/components/LoadSegmentModal";
|
||||
import { SaveAsNewSegmentModal } from "@formbricks/ui/components/SaveAsNewSegmentModal";
|
||||
import { SegmentTitle } from "@formbricks/ui/components/SegmentTitle";
|
||||
import { TargetingIndicator } from "@formbricks/ui/components/TargetingIndicator";
|
||||
import { UpgradePlanNotice } from "@formbricks/ui/components/UpgradePlanNotice";
|
||||
import {
|
||||
cloneBasicSegmentAction,
|
||||
createBasicSegmentAction,
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { LoadingSpinner } from "@/modules/ui/components/loading-spinner";
|
||||
import { debounce } from "lodash";
|
||||
import { SearchIcon } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -10,6 +7,9 @@ import UnsplashImage from "next/image";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { TSurveyBackgroundBgType } from "@formbricks/types/surveys/types";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { LoadingSpinner } from "@formbricks/ui/components/LoadingSpinner";
|
||||
import { getImagesFromUnsplashAction, triggerDownloadUnsplashImageAction } from "../actions";
|
||||
|
||||
interface ImageFromUnsplashSurveyBgProps {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { TSurvey, TSurveyQuestion } from "@formbricks/types/surveys/types";
|
||||
import { validateId } from "@formbricks/types/surveys/validation";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { Label } from "@formbricks/ui/components/Label";
|
||||
|
||||
interface UpdateQuestionIdProps {
|
||||
localSurvey: TSurvey;
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
import { TTeamPermission } from "@/modules/ee/teams/product-teams/types/teams";
|
||||
import { getTeamPermissionFlags } from "@/modules/ee/teams/utils/teams";
|
||||
import { AdvancedOptionToggle } from "@/modules/ui/components/advanced-option-toggle";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import {
|
||||
@@ -21,6 +18,9 @@ import { getAccessFlags } from "@formbricks/lib/membership/utils";
|
||||
import { TActionClass } from "@formbricks/types/action-classes";
|
||||
import { TOrganizationRole } from "@formbricks/types/memberships";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { AdvancedOptionToggle } from "@formbricks/ui/components/AdvancedOptionToggle";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Input } from "@formbricks/ui/components/Input";
|
||||
import { AddActionModal } from "./AddActionModal";
|
||||
|
||||
interface WhenToSendCardProps {
|
||||
|
||||
@@ -366,18 +366,6 @@ export const logicRules = {
|
||||
},
|
||||
],
|
||||
},
|
||||
[TSurveyQuestionTypeEnum.ContactInfo]: {
|
||||
options: [
|
||||
{
|
||||
label: "environments.surveys.edit.is_submitted",
|
||||
value: ZSurveyLogicConditionsOperator.Enum.isSubmitted,
|
||||
},
|
||||
{
|
||||
label: "environments.surveys.edit.is_skipped",
|
||||
value: ZSurveyLogicConditionsOperator.Enum.isSkipped,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
["variable.text"]: {
|
||||
options: [
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { cache as reactCache } from "react";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { cache } from "@formbricks/lib/cache";
|
||||
import { userCache } from "@formbricks/lib/user/cache";
|
||||
import { DatabaseError } from "@formbricks/types/errors";
|
||||
|
||||
export const getUserEmail = reactCache(
|
||||
(userId: string): Promise<string | null> =>
|
||||
cache(
|
||||
async () => {
|
||||
try {
|
||||
const user = await prisma.user.findUnique({ where: { id: userId }, select: { email: true } });
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return user.email;
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
throw new DatabaseError(error.message);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
[`getUserEmail-${userId}`],
|
||||
{
|
||||
tags: [userCache.tag.byId(userId)],
|
||||
}
|
||||
)()
|
||||
);
|
||||
@@ -1,9 +1,7 @@
|
||||
import { TComboboxGroupedOption, TComboboxOption } from "@/modules/ui/components/input-combo-box";
|
||||
import { EyeOffIcon, FileDigitIcon, FileType2Icon } from "lucide-react";
|
||||
import { HTMLInputTypeAttribute } from "react";
|
||||
import { getLocalizedValue } from "@formbricks/lib/i18n/utils";
|
||||
import { isConditionGroup } from "@formbricks/lib/surveyLogic/utils";
|
||||
import { translate } from "@formbricks/lib/templates";
|
||||
import { getQuestionTypes } from "@formbricks/lib/utils/questions";
|
||||
import { recallToHeadline } from "@formbricks/lib/utils/recall";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
@@ -15,14 +13,13 @@ import {
|
||||
TSurvey,
|
||||
TSurveyLogic,
|
||||
TSurveyLogicAction,
|
||||
TSurveyLogicActions,
|
||||
TSurveyLogicConditionsOperator,
|
||||
TSurveyQuestion,
|
||||
TSurveyQuestionId,
|
||||
TSurveyQuestionTypeEnum,
|
||||
TSurveyVariable,
|
||||
} from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { TComboboxGroupedOption, TComboboxOption } from "@formbricks/ui/components/InputCombobox";
|
||||
import { TLogicRuleOption, logicRules } from "./logicRuleEngine";
|
||||
|
||||
// formats the text to highlight specific parts of the text with slashes
|
||||
@@ -150,10 +147,6 @@ export const actionObjectiveOptions: TComboboxOption[] = [
|
||||
{ label: "environments.surveys.edit.jump_to_question", value: "jumpToQuestion" },
|
||||
];
|
||||
|
||||
export const hasJumpToQuestionAction = (actions: TSurveyLogicActions): boolean => {
|
||||
return actions.some((action) => action.objective === "jumpToQuestion");
|
||||
};
|
||||
|
||||
const getQuestionOperatorOptions = (question: TSurveyQuestion): TComboboxOption[] => {
|
||||
let options: TLogicRuleOption;
|
||||
|
||||
@@ -610,10 +603,8 @@ export const getMatchValueProps = (
|
||||
options: groupedOptions,
|
||||
};
|
||||
} else if (selectedVariable?.type === "number") {
|
||||
const allowedQuestions = questions.filter(
|
||||
(question) =>
|
||||
[TSurveyQuestionTypeEnum.Rating, TSurveyQuestionTypeEnum.NPS].includes(question.type) ||
|
||||
(question.type === TSurveyQuestionTypeEnum.OpenText && question.inputType === "number")
|
||||
const allowedQuestions = questions.filter((question) =>
|
||||
[TSurveyQuestionTypeEnum.Rating, TSurveyQuestionTypeEnum.NPS].includes(question.type)
|
||||
);
|
||||
|
||||
const questionOptions = allowedQuestions.map((question) => {
|
||||
@@ -949,10 +940,8 @@ export const getActionValueOptions = (
|
||||
|
||||
return groupedOptions;
|
||||
} else if (selectedVariable.type === "number") {
|
||||
const allowedQuestions = questions.filter(
|
||||
(question) =>
|
||||
[TSurveyQuestionTypeEnum.Rating, TSurveyQuestionTypeEnum.NPS].includes(question.type) ||
|
||||
(question.type === TSurveyQuestionTypeEnum.OpenText && question.inputType === "number")
|
||||
const allowedQuestions = questions.filter((question) =>
|
||||
[TSurveyQuestionTypeEnum.Rating, TSurveyQuestionTypeEnum.NPS].includes(question.type)
|
||||
);
|
||||
|
||||
const questionOptions = allowedQuestions.map((question) => {
|
||||
@@ -1159,10 +1148,6 @@ export const findHiddenFieldUsedInLogic = (survey: TSurvey, hiddenFieldId: strin
|
||||
return survey.questions.findIndex((question) => question.logic?.some(isUsedInLogicRule));
|
||||
};
|
||||
|
||||
export const getSurveyFollowUpActionDefaultBody = (locale: TUserLocale) => {
|
||||
return translate("follow_ups_modal_action_body", locale) as string;
|
||||
};
|
||||
|
||||
export const findEndingCardUsedInLogic = (survey: TSurvey, endingCardId: string): number => {
|
||||
const isUsedInAction = (action: TSurveyLogicAction): boolean => {
|
||||
return action.objective === "jumpToQuestion" && action.target === endingCardId;
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
import { getUserEmail } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/user";
|
||||
import {
|
||||
getAdvancedTargetingPermission,
|
||||
getMultiLanguagePermission,
|
||||
getSurveyFollowUpsPermission,
|
||||
} from "@/modules/ee/license-check/lib/utils";
|
||||
import { getProductPermissionByUserId } from "@/modules/ee/teams/lib/roles";
|
||||
import { getTeamPermissionFlags } from "@/modules/ee/teams/utils/teams";
|
||||
import { ErrorComponent } from "@/modules/ui/components/error-component";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { getAdvancedTargetingPermission, getMultiLanguagePermission } from "@formbricks/ee/lib/service";
|
||||
import { getActionClasses } from "@formbricks/lib/actionClass/service";
|
||||
import { getAttributeClasses } from "@formbricks/lib/attributeClass/service";
|
||||
import { authOptions } from "@formbricks/lib/authOptions";
|
||||
import {
|
||||
DEFAULT_LOCALE,
|
||||
IS_FORMBRICKS_CLOUD,
|
||||
MAIL_FROM,
|
||||
SURVEY_BG_COLORS,
|
||||
UNSPLASH_ACCESS_KEY,
|
||||
} from "@formbricks/lib/constants";
|
||||
@@ -28,6 +21,7 @@ import { getResponseCountBySurveyId } from "@formbricks/lib/response/service";
|
||||
import { getSegments } from "@formbricks/lib/segment/service";
|
||||
import { getSurvey } from "@formbricks/lib/survey/service";
|
||||
import { getUserLocale } from "@formbricks/lib/user/service";
|
||||
import { ErrorComponent } from "@formbricks/ui/components/ErrorComponent";
|
||||
import { SurveyEditor } from "./components/SurveyEditor";
|
||||
|
||||
export const generateMetadata = async (props) => {
|
||||
@@ -63,7 +57,6 @@ const Page = async (props) => {
|
||||
getServerSession(authOptions),
|
||||
getSegments(params.environmentId),
|
||||
]);
|
||||
|
||||
if (!session) {
|
||||
throw new Error(t("common.session_not_found"));
|
||||
}
|
||||
@@ -88,9 +81,6 @@ const Page = async (props) => {
|
||||
|
||||
const isUserTargetingAllowed = await getAdvancedTargetingPermission(organization);
|
||||
const isMultiLanguageAllowed = await getMultiLanguagePermission(organization);
|
||||
const isSurveyFollowUpsAllowed = await getSurveyFollowUpsPermission(organization);
|
||||
|
||||
const userEmail = await getUserEmail(session.user.id);
|
||||
|
||||
if (
|
||||
!survey ||
|
||||
@@ -98,7 +88,6 @@ const Page = async (props) => {
|
||||
!actionClasses ||
|
||||
!attributeClasses ||
|
||||
!product ||
|
||||
!userEmail ||
|
||||
isSurveyCreationDeletionDisabled
|
||||
) {
|
||||
return <ErrorComponent />;
|
||||
@@ -125,9 +114,6 @@ const Page = async (props) => {
|
||||
isUnsplashConfigured={UNSPLASH_ACCESS_KEY ? true : false}
|
||||
isCxMode={isCxMode}
|
||||
locale={locale ?? DEFAULT_LOCALE}
|
||||
mailFrom={MAIL_FROM ?? "hola@formbricks.com"}
|
||||
isSurveyFollowUpsAllowed={isSurveyFollowUpsAllowed}
|
||||
userEmail={userEmail}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const ZCreateSurveyFollowUpFormSchema = z.object({
|
||||
followUpName: z.string().trim().min(1, "Name is required"),
|
||||
triggerType: z.enum(["response", "endings"]),
|
||||
endingIds: z.array(z.string().cuid2()).nullable(),
|
||||
emailTo: z.string().trim().min(1, "To is required"),
|
||||
replyTo: z.array(z.string().email()).min(1, "Replies must have at least one email"),
|
||||
subject: z.string().trim().min(1, "Subject is required"),
|
||||
body: z.string().trim().min(1, "Body is required"),
|
||||
});
|
||||
|
||||
export type TCreateSurveyFollowUpForm = z.infer<typeof ZCreateSurveyFollowUpFormSchema>;
|
||||
@@ -39,5 +39,4 @@ export const getMinimalSurvey = (locale: string): TSurvey => ({
|
||||
isVerifyEmailEnabled: false,
|
||||
isSingleResponsePerEmailEnabled: false,
|
||||
variables: [],
|
||||
followUps: [],
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user