feat: Add option to customize link survey url using NEXT_PUBLIC_SURVEY_BASE_URL (#787)

This commit is contained in:
Matti Nannt
2023-09-08 14:01:56 +09:00
committed by GitHub
parent 38092f8a7c
commit bf6ed3576c
8 changed files with 48 additions and 15 deletions

View File

@@ -132,6 +132,18 @@ const nextConfig = {
},
];
},
async rewrites() {
return {
fallback: [
// These rewrites are checked after both pages/public files
// and dynamic routes are checked
{
source: "/:path*",
destination: `https://app.formbricks.com/s/:path*`,
},
],
};
},
};
export default withPlausibleProxy({ customDomain: "https://plausible.formbricks.com" })(

View File

@@ -6,7 +6,17 @@ import defaultTheme from "tailwindcss/defaultTheme";
import typographyStyles from "./typography";
export default {
content: ["./**/*.{js,mjs,jsx,ts,tsx,mdx}"],
trailingSlash: true,
content: [
// app content
"./app/**/*.{js,mjs,jsx,ts,tsx,mdx}", // Note the addition of the `app` directory.
"./pages/**/*.{js,mjs,jsx,ts,tsx,mdx}",
"./components/**/*.{js,mjs,jsx,ts,tsx,mdx}",
"./lib/**/*.{js,mjs,jsx,ts,tsx,mdx}",
"./mdx/**/*.{js,mjs,jsx,ts,tsx,mdx}",
// include packages if not transpiling
"../../packages/ui/components/**/*.{js,ts,jsx,tsx}",
],
darkMode: "class",
theme: {
fontSize: {

View File

@@ -14,6 +14,7 @@ import {
DropdownMenuTrigger,
} from "@/components/shared/DropdownMenu";
import LoadingSpinner from "@/components/shared/LoadingSpinner";
import { SURVEY_BASE_URL } from "@formbricks/lib/constants";
import type { TEnvironment } from "@formbricks/types/v1/environment";
import type { TSurveyWithAnalytics } from "@formbricks/types/v1/surveys";
import {
@@ -27,7 +28,7 @@ import {
} from "@heroicons/react/24/solid";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useMemo, useState } from "react";
import toast from "react-hot-toast";
interface SurveyDropDownMenuProps {
@@ -47,6 +48,8 @@ export default function SurveyDropDownMenu({
const [loading, setLoading] = useState(false);
const router = useRouter();
const surveyUrl = useMemo(() => SURVEY_BASE_URL + survey.id, [survey]);
const handleDeleteSurvey = async (survey) => {
setLoading(true);
try {
@@ -161,9 +164,7 @@ export default function SurveyDropDownMenu({
<button
className="flex w-full items-center"
onClick={() => {
navigator.clipboard.writeText(
`${window.location.protocol}//${window.location.host}/s/${survey.id}`
);
navigator.clipboard.writeText(surveyUrl);
toast.success("Copied link to clipboard");
}}>
<LinkIcon className="mr-2 h-4 w-4" />

View File

@@ -1,13 +1,12 @@
"use client";
import CodeBlock from "@/components/shared/CodeBlock";
// import Modal from "@/components/shared/Modal";
import { Dialog, DialogContent } from "@formbricks/ui";
import { SURVEY_BASE_URL } from "@formbricks/lib/constants";
import { TSurvey } from "@formbricks/types/v1/surveys";
import { Button } from "@formbricks/ui";
import { Button, Dialog, DialogContent } from "@formbricks/ui";
import { CheckIcon } from "@heroicons/react/24/outline";
import { CodeBracketIcon, DocumentDuplicateIcon, EyeIcon } from "@heroicons/react/24/solid";
import { useRef, useState } from "react";
import { useMemo, useRef, useState } from "react";
import toast from "react-hot-toast";
interface LinkSurveyModalProps {
@@ -20,10 +19,12 @@ export default function LinkSurveyModal({ survey, open, setOpen }: LinkSurveyMod
const linkTextRef = useRef(null);
const [showEmbed, setShowEmbed] = useState(false);
const surveyUrl = useMemo(() => SURVEY_BASE_URL + survey.id, [survey]);
const iframeCode = `<div style="position: relative; height:100vh; max-height:100vh;
overflow:auto;">
<iframe
src="${window.location.protocol}//${window.location.host}/s/${survey.id}"
src="${surveyUrl}"
frameborder="0" style="position: absolute; left:0;
top:0; width:100%; height:100%; border:0;">
</iframe></div>`;
@@ -67,7 +68,9 @@ top:0; width:100%; height:100%; border:0;">
<span
style={{
wordBreak: "break-all",
}}>{`${window.location.protocol}//${window.location.host}/s/${survey.id}`}</span>
}}>
{surveyUrl}
</span>
</div>
</div>
)}
@@ -89,9 +92,7 @@ top:0; width:100%; height:100%; border:0;">
variant="secondary"
onClick={() => {
setShowEmbed(false);
navigator.clipboard.writeText(
`${window.location.protocol}//${window.location.host}/s/${survey.id}`
);
navigator.clipboard.writeText(surveyUrl);
toast.success("URL copied to clipboard!");
}}
title="Copy survey link to clipboard"
@@ -105,7 +106,7 @@ top:0; width:100%; height:100%; border:0;">
title="Preview survey"
aria-label="Preview survey"
className="flex justify-center"
href={`${window.location.protocol}//${window.location.host}/s/${survey.id}?preview=true`}
href={`${surveyUrl}?preview=true`}
target="_blank"
EndIcon={EyeIcon}>
Preview

View File

@@ -64,6 +64,7 @@ export const env = createEnv({
NEXT_PUBLIC_POSTHOG_API_KEY: z.string().optional(),
NEXT_PUBLIC_POSTHOG_API_HOST: z.string().optional(),
NEXT_PUBLIC_SENTRY_DSN: z.string().optional(),
NEXT_PUBLIC_SURVEY_BASE_URL: z.string().optional(),
},
/*
* Due to how Next.js bundles environment variables on Edge and Client,

View File

@@ -4,7 +4,10 @@ import { createId } from "@paralleldrive/cuid2";
/** @type {import('next').NextConfig} */
const isCloud = process.env.NEXT_PUBLIC_IS_FORMBRICKS_CLOUD === "1";
const nextConfig = {
assetPrefix: isCloud ? process.env.NEXT_PUBLIC_WEBAPP_URL : undefined,
output: "standalone",
experimental: {
serverActions: true,

View File

@@ -16,6 +16,10 @@ export const WEBAPP_URL =
RENDER_URL ||
"http://localhost:3000";
export const SURVEY_BASE_URL = process.env.NEXT_PUBLIC_SURVEY_BASE_URL
? process.env.NEXT_PUBLIC_SURVEY_BASE_URL + "/"
: `${WEBAPP_URL}/s/`;
// Other
export const INTERNAL_SECRET = process.env.INTERNAL_SECRET || "";
export const CRON_SECRET = process.env.CRON_SECRET;

View File

@@ -68,6 +68,7 @@
"NEXT_PUBLIC_FORMBRICKS_URL",
"NEXT_PUBLIC_IMPRINT_URL",
"NEXT_PUBLIC_SENTRY_DSN",
"NEXT_PUBLIC_SURVEY_BASE_URL",
"NEXT_PUBLIC_VERCEL_URL",
"NODE_ENV",
"NEXT_PUBLIC_POSTHOG_API_HOST",