mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-31 16:22:06 -06:00
chore: prepare 2.2 launch (#2783)
This commit is contained in:
@@ -13,8 +13,8 @@
|
||||
"dependencies": {
|
||||
"@formbricks/js": "workspace:*",
|
||||
"@formbricks/ui": "workspace:*",
|
||||
"lucide-react": "^0.379.0",
|
||||
"next": "14.2.3",
|
||||
"lucide-react": "^0.395.0",
|
||||
"next": "14.2.4",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1"
|
||||
},
|
||||
|
||||
@@ -8,6 +8,101 @@ export const metadata = {
|
||||
|
||||
# Migration Guide
|
||||
|
||||
## v2.2
|
||||
|
||||
Formbricks v2.2 introduces XM research presets into your products with a brand new product onboarding. Our objective is to make user research “obviously easy”, industry by industry. And we're starting with Software-as-a-Service and E-Commerce.
|
||||
|
||||
### Steps to Migrate
|
||||
|
||||
This guide is for users who are self-hosting Formbricks using our one-click setup. If you are using a different setup, you might adjust the commands accordingly.
|
||||
|
||||
To run all these steps, please navigate to the `formbricks` folder where your `docker-compose.yml` file is located.
|
||||
|
||||
1. **Backup your Database**: This is a crucial step. Please make sure to backup your database before proceeding with the upgrade. You can use the following command to backup your database:
|
||||
|
||||
<Col>
|
||||
<CodeGroup title="Backup Postgres">
|
||||
|
||||
```bash
|
||||
docker exec formbricks-postgres-1 pg_dump -Fc -U postgres -d formbricks > formbricks_pre_v2.2_$(date +%Y%m%d_%H%M%S).dump
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
|
||||
<Note>
|
||||
If you run into “No such container”, use `docker ps` to find your container name, e.g.
|
||||
`formbricks_postgres_1`.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
If you prefer storing the backup as an `*.sql` file remove the `-Fc` (custom format) option. In case of a
|
||||
restore scenario you will need to use `psql` then with an empty `formbricks` database.
|
||||
</Note>
|
||||
|
||||
2. Pull the latest version of Formbricks:
|
||||
|
||||
<Col>
|
||||
<CodeGroup title="Stop the containers">
|
||||
|
||||
```bash
|
||||
docker compose pull
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
|
||||
3. Stop the running Formbricks instance & remove the related containers:
|
||||
|
||||
<Col>
|
||||
<CodeGroup title="Stop the containers">
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
|
||||
4. Restarting the containers with the latest version of Formbricks:
|
||||
|
||||
<Col>
|
||||
<CodeGroup title="Restart the containers">
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
|
||||
5. Now let's migrate the data to the latest schema:
|
||||
|
||||
<Note>To find your Docker Network name for your Postgres Database, find it using `docker network ls`</Note>
|
||||
|
||||
<Col>
|
||||
<CodeGroup title="Migrate the data">
|
||||
|
||||
```bash
|
||||
docker pull ghcr.io/formbricks/data-migrations:latest && \
|
||||
docker run --rm \
|
||||
--network=formbricks_default \
|
||||
-e DATABASE_URL="postgresql://postgres:postgres@postgres:5432/formbricks?schema=public" \
|
||||
-e UPGRADE_TO_VERSION="v2.2" \
|
||||
ghcr.io/formbricks/data-migrations:latest
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
|
||||
The above command will migrate your data to the latest schema. This is a crucial step to migrate your existing data to the new structure. Only if the script runs successful, changes are made to the database. The script can safely run multiple times.
|
||||
|
||||
6. That's it! Once the migration is complete, you can **now access your Formbricks instance** at the same URL as before.
|
||||
|
||||
### Changes in Environment Variables
|
||||
|
||||
- `ONBOARDING_DISABLED` is now deprecated since we replaced the user onboarding with a product onboarding that only runs when creating a new product.
|
||||
|
||||
## v2.1
|
||||
|
||||
Formbricks v2.1 introduces more options for creating No-Code Actions and lays the foundation for easier self-hosting of Formbricks starting with an Onboarding for fresh instances.
|
||||
|
||||
@@ -12,34 +12,34 @@
|
||||
},
|
||||
"browserslist": "defaults, not ie <= 11",
|
||||
"dependencies": {
|
||||
"@algolia/autocomplete-core": "^1.17.0",
|
||||
"@calcom/embed-react": "^1.4.0",
|
||||
"@algolia/autocomplete-core": "^1.17.2",
|
||||
"@calcom/embed-react": "^1.5.0",
|
||||
"@docsearch/css": "3",
|
||||
"@docsearch/react": "^3.6.0",
|
||||
"@formbricks/lib": "workspace:*",
|
||||
"@formbricks/types": "workspace:*",
|
||||
"@formbricks/ui": "workspace:*",
|
||||
"@headlessui/react": "^2.0.3",
|
||||
"@headlessui/tailwindcss": "^0.2.0",
|
||||
"@headlessui/react": "^2.0.4",
|
||||
"@headlessui/tailwindcss": "^0.2.1",
|
||||
"@mapbox/rehype-prism": "^0.9.0",
|
||||
"@mdx-js/loader": "^3.0.1",
|
||||
"@mdx-js/react": "^3.0.1",
|
||||
"@next/mdx": "14.2.3",
|
||||
"@next/mdx": "14.2.4",
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@sindresorhus/slugify": "^2.2.1",
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"acorn": "^8.11.3",
|
||||
"acorn": "^8.12.0",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"clsx": "^2.1.1",
|
||||
"fast-glob": "^3.3.2",
|
||||
"flexsearch": "^0.7.43",
|
||||
"framer-motion": "11.1.9",
|
||||
"framer-motion": "11.2.11",
|
||||
"lottie-web": "^5.12.2",
|
||||
"lucide": "^0.378.0",
|
||||
"lucide-react": "^0.378.0",
|
||||
"lucide": "^0.395.0",
|
||||
"lucide-react": "^0.395.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"mdx-annotations": "^0.1.4",
|
||||
"next": "14.2.3",
|
||||
"next": "14.2.4",
|
||||
"next-plausible": "^3.12.0",
|
||||
"next-seo": "^6.5.0",
|
||||
"next-sitemap": "^4.2.3",
|
||||
@@ -59,7 +59,7 @@
|
||||
"sharp": "^0.33.4",
|
||||
"shiki": "^0.14.7",
|
||||
"simple-functional-loader": "^1.2.1",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"unist-util-filter": "^5.0.1",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"zustand": "^4.5.2"
|
||||
@@ -67,7 +67,7 @@
|
||||
"devDependencies": {
|
||||
"@formbricks/config-typescript": "workspace:*",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/react-highlight-words": "^0.16.7",
|
||||
"@types/react-highlight-words": "^0.20.0",
|
||||
"@formbricks/eslint-config": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,22 +19,22 @@
|
||||
"devDependencies": {
|
||||
"@chromatic-com/storybook": "^1.5.0",
|
||||
"@formbricks/config-typescript": "workspace:*",
|
||||
"@storybook/addon-essentials": "^8.1.5",
|
||||
"@storybook/addon-interactions": "^8.1.5",
|
||||
"@storybook/addon-links": "^8.1.5",
|
||||
"@storybook/addon-onboarding": "^8.1.5",
|
||||
"@storybook/blocks": "^8.1.5",
|
||||
"@storybook/react": "^8.1.5",
|
||||
"@storybook/react-vite": "^8.1.5",
|
||||
"@storybook/test": "^8.1.5",
|
||||
"@typescript-eslint/eslint-plugin": "^7.12.0",
|
||||
"@typescript-eslint/parser": "^7.12.0",
|
||||
"@vitejs/plugin-react": "^4.3.0",
|
||||
"esbuild": "^0.21.4",
|
||||
"@storybook/addon-essentials": "^8.1.10",
|
||||
"@storybook/addon-interactions": "^8.1.10",
|
||||
"@storybook/addon-links": "^8.1.10",
|
||||
"@storybook/addon-onboarding": "^8.1.10",
|
||||
"@storybook/blocks": "^8.1.10",
|
||||
"@storybook/react": "^8.1.10",
|
||||
"@storybook/react-vite": "^8.1.10",
|
||||
"@storybook/test": "^8.1.10",
|
||||
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
||||
"@typescript-eslint/parser": "^7.13.1",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"esbuild": "^0.21.5",
|
||||
"eslint-plugin-storybook": "^0.8.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"storybook": "^8.1.5",
|
||||
"storybook": "^8.1.10",
|
||||
"tsup": "^8.1.0",
|
||||
"vite": "^5.2.12"
|
||||
"vite": "^5.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { STRIPE_PRICE_LOOKUP_KEYS } from "@formbricks/lib/constants";
|
||||
import { getOrganizationByEnvironmentId } from "@formbricks/lib/organization/service";
|
||||
import { upgradePlanAction } from "../actions";
|
||||
|
||||
const Page = async ({ params }) => {
|
||||
const organization = await getOrganizationByEnvironmentId(params.environmentId);
|
||||
if (!organization) {
|
||||
throw new Error("Organization not found");
|
||||
}
|
||||
|
||||
const { status, newPlan, url } = await upgradePlanAction(
|
||||
organization.id,
|
||||
params.environmentId,
|
||||
STRIPE_PRICE_LOOKUP_KEYS.UNLIMITED_99
|
||||
);
|
||||
|
||||
if (status != 200) {
|
||||
throw new Error("Something went wrong");
|
||||
}
|
||||
if (newPlan && url) {
|
||||
redirect(url);
|
||||
} else if (!newPlan) {
|
||||
redirect(`/billing-confirmation?environmentId=${params.environmentId}`);
|
||||
} else {
|
||||
throw new Error("Something went wrong");
|
||||
}
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@formbricks/web",
|
||||
"version": "2.1.0",
|
||||
"version": "2.2.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"clean": "rimraf .turbo node_modules .next",
|
||||
@@ -26,47 +26,47 @@
|
||||
"@formbricks/config-tailwind": "workspace:*",
|
||||
"@formbricks/types": "workspace:*",
|
||||
"@formbricks/ui": "workspace:*",
|
||||
"@hookform/resolvers": "^3.4.2",
|
||||
"@hookform/resolvers": "^3.6.0",
|
||||
"@json2csv/node": "^7.0.6",
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@radix-ui/react-collapsible": "^1.0.3",
|
||||
"@react-email/components": "^0.0.19",
|
||||
"@sentry/nextjs": "^8.4.0",
|
||||
"@sentry/nextjs": "^8.10.0",
|
||||
"@vercel/og": "^0.6.2",
|
||||
"@vercel/speed-insights": "^1.0.11",
|
||||
"@vercel/speed-insights": "^1.0.12",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"dotenv": "^16.4.5",
|
||||
"encoding": "^0.1.13",
|
||||
"framer-motion": "11.2.6",
|
||||
"googleapis": "^137.1.0",
|
||||
"jiti": "^1.21.0",
|
||||
"framer-motion": "11.2.11",
|
||||
"googleapis": "^140.0.0",
|
||||
"jiti": "^1.21.6",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"lodash": "^4.17.21",
|
||||
"lru-cache": "^10.2.2",
|
||||
"lucide-react": "^0.379.0",
|
||||
"lucide-react": "^0.395.0",
|
||||
"mime": "^4.0.3",
|
||||
"next": "15.0.0-rc.0",
|
||||
"optional": "^0.1.4",
|
||||
"otplib": "^12.0.1",
|
||||
"papaparse": "^5.4.1",
|
||||
"posthog-js": "^1.135.2",
|
||||
"posthog-js": "^1.139.3",
|
||||
"prismjs": "^1.29.0",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "19.0.0-rc-935180c7e0-20240524",
|
||||
"react-dom": "19.0.0-rc-935180c7e0-20240524",
|
||||
"react-hook-form": "^7.51.5",
|
||||
"react-hook-form": "^7.52.0",
|
||||
"react-hot-toast": "^2.4.1",
|
||||
"redis": "^4.6.14",
|
||||
"sharp": "^0.33.4",
|
||||
"ua-parser-js": "^1.0.37",
|
||||
"webpack": "^5.91.0",
|
||||
"ua-parser-js": "^1.0.38",
|
||||
"webpack": "^5.92.0",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@formbricks/config-typescript": "workspace:*",
|
||||
"@neshca/cache-handler": "^1.3.2",
|
||||
"@types/bcryptjs": "^2.4.6",
|
||||
"@types/lodash": "^4.17.4",
|
||||
"@types/lodash": "^4.17.5",
|
||||
"@types/markdown-it": "^14.1.1",
|
||||
"@types/papaparse": "^5.3.14",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
|
||||
@@ -36,10 +36,10 @@
|
||||
"@formbricks/eslint-config": "workspace:*",
|
||||
"eslint": "^8.57.0",
|
||||
"husky": "^9.0.11",
|
||||
"lint-staged": "^15.2.5",
|
||||
"lint-staged": "^15.2.7",
|
||||
"rimraf": "^5.0.7",
|
||||
"tsx": "^4.11.0",
|
||||
"turbo": "^2.0.1"
|
||||
"tsx": "^4.15.6",
|
||||
"turbo": "^2.0.4"
|
||||
},
|
||||
"lint-staged": {
|
||||
"(apps|packages)/**/*.{js,ts,jsx,tsx}": [
|
||||
@@ -63,7 +63,7 @@
|
||||
"showDetails": true
|
||||
},
|
||||
"dependencies": {
|
||||
"@changesets/cli": "^2.27.3",
|
||||
"@changesets/cli": "^2.27.5",
|
||||
"playwright": "^1.44.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
"@formbricks/config-typescript": "workspace:*",
|
||||
"@formbricks/types": "workspace:*",
|
||||
"@formbricks/eslint-config": "workspace:*",
|
||||
"terser": "^5.31.0",
|
||||
"vite": "^5.2.11",
|
||||
"terser": "^5.31.1",
|
||||
"vite": "^5.3.1",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@next/eslint-plugin-next": "^14.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^7.10.0",
|
||||
"@typescript-eslint/parser": "^7.10.0",
|
||||
"@vercel/style-guide": "^5.2.0",
|
||||
"eslint-config-next": "^14.2.3",
|
||||
"@next/eslint-plugin-next": "^14.2.4",
|
||||
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
||||
"@typescript-eslint/parser": "^7.13.1",
|
||||
"@vercel/style-guide": "^6.0.0",
|
||||
"eslint-config-next": "^14.2.4",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-config-turbo": "^2.0.0",
|
||||
"eslint-plugin-react": "7.34.1",
|
||||
"eslint-config-turbo": "^2.0.4",
|
||||
"eslint-plugin-react": "7.34.3",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-refresh": "^0.4.7"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-tailwindcss": "^0.5.14"
|
||||
"prettier": "^3.3.2",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"postcss": "^8.4.38",
|
||||
"tailwindcss": "^3.4.3"
|
||||
"tailwindcss": "^3.4.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"clean": "rimraf node_modules dist turbo"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.12.12",
|
||||
"@types/node": "20.14.5",
|
||||
"@types/react": "18.3.3",
|
||||
"@types/react-dom": "18.3.0",
|
||||
"typescript": "5.4.5"
|
||||
|
||||
@@ -37,11 +37,12 @@
|
||||
"data-migration:extended-noCodeActions": "ts-node ./data-migrations/20240524053239_extends_no_code_action_schema/data-migration.ts",
|
||||
"data-migration:v2.1": "pnpm data-migration:extended-noCodeActions",
|
||||
"data-migration:adds_app_and_website_status_indicator": "ts-node ./data-migrations/20240610055828_adds_app_and_website_status_indicators/data-migration.ts",
|
||||
"data-migration:product-config": "ts-node ./data-migrations/20240612115151_adds_product_config/data-migration.ts"
|
||||
"data-migration:product-config": "ts-node ./data-migrations/20240612115151_adds_product_config/data-migration.ts",
|
||||
"data-migration:v2.2": "pnpm data-migration:adds_app_and_website_status_indicator && pnpm data-migration:product-config"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "^5.14.0",
|
||||
"@prisma/extension-accelerate": "^1.0.0",
|
||||
"@prisma/client": "^5.15.1",
|
||||
"@prisma/extension-accelerate": "^1.1.0",
|
||||
"dotenv-cli": "^7.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -49,7 +50,7 @@
|
||||
"@formbricks/types": "workspace:*",
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@formbricks/eslint-config": "workspace:*",
|
||||
"prisma": "^5.14.0",
|
||||
"prisma": "^5.15.1",
|
||||
"prisma-dbml-generator": "^0.12.0",
|
||||
"prisma-json-types-generator": "^3.0.4",
|
||||
"ts-node": "^10.9.2",
|
||||
|
||||
@@ -25,14 +25,14 @@
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@radix-ui/react-collapsible": "^1.0.3",
|
||||
"https-proxy-agent": "^7.0.4",
|
||||
"lucide-react": "^0.390.0",
|
||||
"next": "^14.2.3",
|
||||
"lucide-react": "^0.395.0",
|
||||
"next": "^14.2.4",
|
||||
"next-auth": "^4.24.7",
|
||||
"node-fetch": "^3.3.2",
|
||||
"react-hook-form": "^7.51.5",
|
||||
"react-hook-form": "^7.52.0",
|
||||
"react-hot-toast": "^2.4.1",
|
||||
"server-only": "^0.0.1",
|
||||
"stripe": "^15.8.0",
|
||||
"stripe": "^15.12.0",
|
||||
"zod": "^3.23.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ export function PreviewEmailTemplate({ survey, surveyUrl, styling }: PreviewEmai
|
||||
const defaultLanguageCode = "default";
|
||||
const firstQuestion = survey.questions[0];
|
||||
|
||||
const brandColor = styling.brandColor?.light || COLOR_DEFAULTS.brandColor;
|
||||
const brandColor = styling.brandColor?.light ?? COLOR_DEFAULTS.brandColor;
|
||||
|
||||
switch (firstQuestion.type) {
|
||||
case TSurveyQuestionTypeEnum.OpenText:
|
||||
@@ -109,7 +109,7 @@ export function PreviewEmailTemplate({ survey, surveyUrl, styling }: PreviewEmai
|
||||
{Array.from({ length: 11 }, (_, i) => (
|
||||
<EmailButton
|
||||
className="border-input-border-color m-0 inline-flex h-10 w-10 items-center justify-center border p-0 text-slate-800"
|
||||
href={`${urlWithPrefilling}${firstQuestion.id}=${i}`}
|
||||
href={`${urlWithPrefilling}${firstQuestion.id}=${i.toString()}`}
|
||||
key={i}>
|
||||
{i}
|
||||
</EmailButton>
|
||||
@@ -137,7 +137,7 @@ export function PreviewEmailTemplate({ survey, surveyUrl, styling }: PreviewEmai
|
||||
case TSurveyQuestionTypeEnum.CTA:
|
||||
return (
|
||||
<EmailTemplateWrapper styling={styling} surveyUrl={url}>
|
||||
<Text className="text-question-color m-0 block text-base font-semibold leading-6">
|
||||
<Text className="text-question-color m-0 block text-base font-semibold leading-6">
|
||||
{getLocalizedValue(firstQuestion.headline, defaultLanguageCode)}
|
||||
</Text>
|
||||
<Container className="text-question-color ml-0 mt-2 text-sm font-normal leading-6">
|
||||
@@ -193,7 +193,7 @@ export function PreviewEmailTemplate({ survey, surveyUrl, styling }: PreviewEmai
|
||||
"border border-solid border-gray-200": firstQuestion.scale === "number",
|
||||
}
|
||||
)}
|
||||
href={`${urlWithPrefilling}${firstQuestion.id}=${i + 1}`}
|
||||
href={`${urlWithPrefilling}${firstQuestion.id}=${(i + 1).toString()}`}
|
||||
key={i}>
|
||||
{firstQuestion.scale === "smiley" && (
|
||||
<RatingSmiley active={false} idx={i} range={firstQuestion.range} />
|
||||
@@ -214,7 +214,7 @@ export function PreviewEmailTemplate({ survey, surveyUrl, styling }: PreviewEmai
|
||||
</Text>
|
||||
</Column>
|
||||
<Column className="text-right">
|
||||
<Text className="m-0 inline-block p-0 text-right">
|
||||
<Text className="m-0 inline-block p-0 text-right">
|
||||
{getLocalizedValue(firstQuestion.upperLabel, defaultLanguageCode)}
|
||||
</Text>
|
||||
</Column>
|
||||
@@ -311,7 +311,7 @@ export function PreviewEmailTemplate({ survey, surveyUrl, styling }: PreviewEmai
|
||||
</Text>
|
||||
<EmailButton
|
||||
className={cn(
|
||||
"bg-brand-color rounded-custom mx-auto block w-max cursor-pointer appearance-none px-6 py-3 text-sm font-medium ",
|
||||
"bg-brand-color rounded-custom mx-auto block w-max cursor-pointer appearance-none px-6 py-3 text-sm font-medium",
|
||||
isLight(brandColor) ? "text-black" : "text-white"
|
||||
)}>
|
||||
Schedule your meeting
|
||||
|
||||
@@ -54,7 +54,7 @@ interface ResponseFinishedEmailProps {
|
||||
response: TResponse;
|
||||
WEBAPP_URL: string;
|
||||
environmentId: string;
|
||||
organization: TOrganization | null;
|
||||
organization: TOrganization;
|
||||
}
|
||||
|
||||
export function ResponseFinishedEmail({
|
||||
@@ -92,7 +92,7 @@ export function ResponseFinishedEmail({
|
||||
href={`${WEBAPP_URL}/environments/${environmentId}/surveys/${survey.id}/responses?utm_source=email_notification&utm_medium=email&utm_content=view_responses_CTA`}
|
||||
label={
|
||||
responseCount > 1
|
||||
? `View ${responseCount - 1} more ${responseCount === 2 ? "response" : "responses"}`
|
||||
? `View ${String(responseCount - 1).toString()} more ${responseCount === 2 ? "response" : "responses"}`
|
||||
: `View survey summary`
|
||||
}
|
||||
/>
|
||||
@@ -111,7 +111,7 @@ export function ResponseFinishedEmail({
|
||||
Turn off notifications for{" "}
|
||||
<Link
|
||||
className="text-black underline"
|
||||
href={`${WEBAPP_URL}/environments/${environmentId}/settings/notifications?type=unsubscribedOrganizationIds&elementId=${organization?.id}`}>
|
||||
href={`${WEBAPP_URL}/environments/${environmentId}/settings/notifications?type=unsubscribedOrganizationIds&elementId=${organization.id}`}>
|
||||
all newly created forms{" "}
|
||||
</Link>
|
||||
</Text>
|
||||
|
||||
@@ -13,7 +13,7 @@ const getButtonLabel = (count: number): string => {
|
||||
if (count === 1) {
|
||||
return "View Response";
|
||||
}
|
||||
return `View ${count > 2 ? count - 1 : "1"} more Response${count > 2 ? "s" : ""}`;
|
||||
return `View ${count > 2 ? (count - 1).toString() : "1"} more Response${count > 2 ? "s" : ""}`;
|
||||
};
|
||||
|
||||
const convertSurveyStatus = (status: TSurveyStatus): string => {
|
||||
@@ -51,7 +51,7 @@ export const LiveSurveyNotification = ({ environmentId, surveys }: LiveSurveyNot
|
||||
}
|
||||
|
||||
surveyFields.push(
|
||||
<Container className="mt-4" key={`${index}-${surveyResponse.headline}`}>
|
||||
<Container className="mt-4" key={`${index.toString()}-${surveyResponse.headline}`}>
|
||||
<Text className="m-0">{surveyResponse.headline}</Text>
|
||||
{renderEmailResponseValue(surveyResponse.responseValue, surveyResponse.questionType)}
|
||||
</Container>
|
||||
@@ -59,7 +59,7 @@ export const LiveSurveyNotification = ({ environmentId, surveys }: LiveSurveyNot
|
||||
|
||||
// Add <hr/> only when there are 2 or more responses to display, and it's not the last response
|
||||
if (responseCount >= 2 && index < responseCount - 1) {
|
||||
surveyFields.push(<Hr key={`hr-${index}`} />);
|
||||
surveyFields.push(<Hr key={`hr-${index.toString()}`} />);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -61,8 +61,6 @@ const getEmailSubject = (productName: string): string => {
|
||||
return `${productName} User Insights - Last Week by Formbricks`;
|
||||
};
|
||||
|
||||
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||||
|
||||
export const sendEmail = async (emailData: SendEmailDataProps) => {
|
||||
if (IS_SMTP_CONFIGURED) {
|
||||
const transporter = nodemailer.createTransport({
|
||||
@@ -77,7 +75,7 @@ export const sendEmail = async (emailData: SendEmailDataProps) => {
|
||||
debug: DEBUG,
|
||||
} as SMTPTransport.Options);
|
||||
const emailDefaults = {
|
||||
from: `Formbricks <${MAIL_FROM || "noreply@formbricks.com"}>`,
|
||||
from: `Formbricks <${MAIL_FROM ?? "noreply@formbricks.com"}>`,
|
||||
};
|
||||
await transporter.sendMail({ ...emailDefaults, ...emailData });
|
||||
} else {
|
||||
@@ -170,12 +168,16 @@ export const sendResponseFinishedEmail = async (
|
||||
const personEmail = response.personAttributes?.email;
|
||||
const organization = await getOrganizationByEnvironmentId(environmentId);
|
||||
|
||||
if (!organization) {
|
||||
throw new Error("Organization not found");
|
||||
}
|
||||
|
||||
await sendEmail({
|
||||
to: email,
|
||||
subject: personEmail
|
||||
? `${personEmail} just completed your ${survey.name} survey ✅`
|
||||
: `A response for ${survey.name} was completed ✅`,
|
||||
replyTo: personEmail?.toString() || MAIL_FROM,
|
||||
replyTo: personEmail?.toString() ?? MAIL_FROM,
|
||||
html: render(
|
||||
EmailTemplate({
|
||||
content: ResponseFinishedEmail({
|
||||
@@ -227,12 +229,14 @@ export const sendWeeklySummaryNotificationEmail = async (
|
||||
email: string,
|
||||
notificationData: TWeeklySummaryNotificationResponse
|
||||
) => {
|
||||
const startDate = `${notificationData.lastWeekDate.getDate()} ${
|
||||
monthNames[notificationData.lastWeekDate.getMonth()]
|
||||
}`;
|
||||
const endDate = `${notificationData.currentDate.getDate()} ${
|
||||
monthNames[notificationData.currentDate.getMonth()]
|
||||
}`;
|
||||
const startDate = `${notificationData.lastWeekDate.getDate().toString()} ${notificationData.lastWeekDate.toLocaleString(
|
||||
"default",
|
||||
{ month: "short" }
|
||||
)}`;
|
||||
const endDate = `${notificationData.currentDate.getDate().toString()} ${notificationData.currentDate.toLocaleString(
|
||||
"default",
|
||||
{ month: "short" }
|
||||
)}`;
|
||||
const startYear = notificationData.lastWeekDate.getFullYear();
|
||||
const endYear = notificationData.currentDate.getFullYear();
|
||||
await sendEmail({
|
||||
@@ -256,12 +260,14 @@ export const sendNoLiveSurveyNotificationEmail = async (
|
||||
email: string,
|
||||
notificationData: TWeeklySummaryNotificationResponse
|
||||
) => {
|
||||
const startDate = `${notificationData.lastWeekDate.getDate()} ${
|
||||
monthNames[notificationData.lastWeekDate.getMonth()]
|
||||
}`;
|
||||
const endDate = `${notificationData.currentDate.getDate()} ${
|
||||
monthNames[notificationData.currentDate.getMonth()]
|
||||
}`;
|
||||
const startDate = `${notificationData.lastWeekDate.getDate().toString()} ${notificationData.lastWeekDate.toLocaleString(
|
||||
"default",
|
||||
{ month: "short" }
|
||||
)}`;
|
||||
const endDate = `${notificationData.currentDate.getDate().toString()} ${notificationData.currentDate.toLocaleString(
|
||||
"default",
|
||||
{ month: "short" }
|
||||
)}`;
|
||||
const startYear = notificationData.lastWeekDate.getFullYear();
|
||||
const endYear = notificationData.currentDate.getFullYear();
|
||||
await sendEmail({
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"@formbricks/ui": "workspace:*",
|
||||
"@react-email/components": "^0.0.19",
|
||||
"@react-email/render": "^0.0.15",
|
||||
"lucide-react": "^0.390.0",
|
||||
"lucide-react": "^0.395.0",
|
||||
"nodemailer": "^6.9.13",
|
||||
"react-email": "^2.1.4"
|
||||
},
|
||||
|
||||
@@ -59,8 +59,8 @@
|
||||
"@formbricks/config-typescript": "workspace:*",
|
||||
"@formbricks/types": "workspace:*",
|
||||
"@formbricks/eslint-config": "workspace:*",
|
||||
"terser": "^5.31.0",
|
||||
"vite": "^5.2.11",
|
||||
"terser": "^5.31.1",
|
||||
"vite": "^5.3.1",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
"@formbricks/js-core": "workspace:*",
|
||||
"@formbricks/config-typescript": "workspace:*",
|
||||
"@formbricks/eslint-config": "workspace:*",
|
||||
"terser": "^5.31.0",
|
||||
"vite": "^5.2.11",
|
||||
"terser": "^5.31.1",
|
||||
"vite": "^5.3.1",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
"test": "dotenv -e ../../.env -- vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.583.0",
|
||||
"@aws-sdk/s3-presigned-post": "3.583.0",
|
||||
"@aws-sdk/s3-request-presigner": "3.583.0",
|
||||
"@aws-sdk/client-s3": "3.600.0",
|
||||
"@aws-sdk/s3-presigned-post": "3.600.0",
|
||||
"@aws-sdk/s3-request-presigner": "3.600.0",
|
||||
"@formbricks/api": "*",
|
||||
"@formbricks/database": "*",
|
||||
"@formbricks/types": "*",
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@t3-oss/env-nextjs": "^0.10.1",
|
||||
"@ungap/structured-clone": "^1.2.0",
|
||||
"aws-crt": "^1.21.2",
|
||||
"aws-crt": "^1.21.3",
|
||||
"date-fns": "^3.6.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"markdown-it": "^14.1.0",
|
||||
|
||||
@@ -44,14 +44,14 @@
|
||||
"autoprefixer": "^10.4.19",
|
||||
"concurrently": "8.2.2",
|
||||
"@formbricks/eslint-config": "workspace:*",
|
||||
"isomorphic-dompurify": "^2.11.0",
|
||||
"isomorphic-dompurify": "^2.12.0",
|
||||
"postcss": "^8.4.38",
|
||||
"preact": "^10.22.0",
|
||||
"react-date-picker": "^11.0.0",
|
||||
"serve": "14.2.3",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"terser": "^5.31.0",
|
||||
"vite": "^5.2.11",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"terser": "^5.31.1",
|
||||
"vite": "^5.3.1",
|
||||
"vite-plugin-dts": "^3.9.1",
|
||||
"vite-tsconfig-paths": "^4.3.2"
|
||||
}
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
"@formbricks/database": "workspace:*",
|
||||
"@formbricks/lib": "workspace:*",
|
||||
"@formbricks/surveys": "workspace:*",
|
||||
"@lexical/code": "^0.15.0",
|
||||
"@lexical/link": "^0.15.0",
|
||||
"@lexical/list": "^0.15.0",
|
||||
"@lexical/markdown": "^0.15.0",
|
||||
"@lexical/react": "^0.15.0",
|
||||
"@lexical/rich-text": "^0.15.0",
|
||||
"@lexical/table": "^0.15.0",
|
||||
"@lexical/code": "^0.16.0",
|
||||
"@lexical/link": "^0.16.0",
|
||||
"@lexical/list": "^0.16.0",
|
||||
"@lexical/markdown": "^0.16.0",
|
||||
"@lexical/react": "^0.16.0",
|
||||
"@lexical/rich-text": "^0.16.0",
|
||||
"@lexical/table": "^0.16.0",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-dialog": "^1.0.5",
|
||||
@@ -42,8 +42,8 @@
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"lexical": "^0.15.0",
|
||||
"lucide-react": "^0.379.0",
|
||||
"lexical": "^0.16.0",
|
||||
"lucide-react": "^0.395.0",
|
||||
"mime": "^4.0.3",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-confetti": "^6.1.0",
|
||||
|
||||
3067
pnpm-lock.yaml
generated
3067
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user