diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/templates/templates.ts b/apps/web/app/(app)/environments/[environmentId]/surveys/templates/templates.ts index 09a7fb0d31..df6172a9b5 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/templates/templates.ts +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/templates/templates.ts @@ -2635,7 +2635,7 @@ export const minimalSurvey: TSurvey = { languages: [], }; -export const getFirstSurvey = (webAppUrl: string) => ({ +export const getExampleSurveyTemplate = (webAppUrl: string) => ({ ...customSurvey.preset, questions: customSurvey.preset.questions.map( (question) => diff --git a/apps/web/app/api/v1/client/[environmentId]/in-app/sync/[userId]/route.ts b/apps/web/app/api/v1/client/[environmentId]/in-app/sync/[userId]/route.ts index 86b5de96b4..da4bf3bcbe 100644 --- a/apps/web/app/api/v1/client/[environmentId]/in-app/sync/[userId]/route.ts +++ b/apps/web/app/api/v1/client/[environmentId]/in-app/sync/[userId]/route.ts @@ -1,3 +1,4 @@ +import { getExampleSurveyTemplate } from "@/app/(app)/environments/[environmentId]/surveys/templates/templates"; import { sendFreeLimitReachedEventToPosthogBiWeekly } from "@/app/api/v1/client/[environmentId]/in-app/sync/lib/posthog"; import { responses } from "@/app/lib/api/response"; import { transformErrorToDetails } from "@/app/lib/api/validator"; @@ -8,12 +9,13 @@ import { IS_FORMBRICKS_CLOUD, PRICING_APPSURVEYS_FREE_RESPONSES, PRICING_USERTARGETING_FREE_MTU, + WEBAPP_URL, } from "@formbricks/lib/constants"; import { getEnvironment, updateEnvironment } from "@formbricks/lib/environment/service"; import { createPerson, getIsPersonMonthlyActive, getPersonByUserId } from "@formbricks/lib/person/service"; import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; import { COLOR_DEFAULTS } from "@formbricks/lib/styling/constants"; -import { getSyncSurveys, transformToLegacySurvey } from "@formbricks/lib/survey/service"; +import { createSurvey, getSyncSurveys, transformToLegacySurvey } from "@formbricks/lib/survey/service"; import { getMonthlyActiveTeamPeopleCount, getMonthlyTeamResponseCount, @@ -70,9 +72,11 @@ export async function GET( throw new Error("Environment does not exist"); } if (!environment?.widgetSetupCompleted) { + const firstSurvey = getExampleSurveyTemplate(WEBAPP_URL); + await createSurvey(environmentId, firstSurvey); await updateEnvironment(environment.id, { widgetSetupCompleted: true }); } - // check team subscriptons + // check team subscriptions const team = await getTeamByEnvironmentId(environmentId); if (!team) { diff --git a/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts b/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts index 2bad639903..da4734bc8d 100644 --- a/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts +++ b/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts @@ -1,4 +1,4 @@ -import { getFirstSurvey } from "@/app/(app)/environments/[environmentId]/surveys/templates/templates"; +import { getExampleSurveyTemplate } from "@/app/(app)/environments/[environmentId]/surveys/templates/templates"; import { sendFreeLimitReachedEventToPosthogBiWeekly } from "@/app/api/v1/client/[environmentId]/in-app/sync/lib/posthog"; import { responses } from "@/app/lib/api/response"; import { transformErrorToDetails } from "@/app/lib/api/validator"; @@ -77,7 +77,7 @@ export async function GET( } if (!environment?.widgetSetupCompleted) { - const firstSurvey = getFirstSurvey(WEBAPP_URL); + const firstSurvey = getExampleSurveyTemplate(WEBAPP_URL); await createSurvey(environmentId, firstSurvey); await updateEnvironment(environment.id, { widgetSetupCompleted: true }); } diff --git a/packages/database/schema.prisma b/packages/database/schema.prisma index 66b7f7ea8f..53554a4bb6 100644 --- a/packages/database/schema.prisma +++ b/packages/database/schema.prisma @@ -200,7 +200,7 @@ model Display { status DisplayStatus? @@index([surveyId]) - @@index([personId]) + @@index([personId, createdAt]) } model SurveyTrigger { @@ -313,7 +313,7 @@ model Survey { displayPercentage Int? languages SurveyLanguage[] - @@index([environmentId]) + @@index([environmentId, updatedAt]) @@index([segmentId]) } @@ -339,6 +339,7 @@ model ActionClass { actions Action[] @@unique([name, environmentId]) + @@index([environmentId, createdAt]) } model Action { @@ -356,6 +357,7 @@ model Action { @@index([personId, actionClassId, createdAt]) @@index([actionClassId, createdAt]) @@index([personId]) + @@index([createdAt]) } enum EnvironmentType { diff --git a/packages/lib/action/service.ts b/packages/lib/action/service.ts index 8d449ae65b..bcd82e1201 100644 --- a/packages/lib/action/service.ts +++ b/packages/lib/action/service.ts @@ -15,8 +15,7 @@ import { actionClassCache } from "../actionClass/cache"; import { createActionClass, getActionClassByEnvironmentIdAndName } from "../actionClass/service"; import { ITEMS_PER_PAGE, SERVICES_REVALIDATION_INTERVAL } from "../constants"; import { activePersonCache } from "../person/cache"; -import { createPerson, getIsPersonMonthlyActive, getPersonByUserId } from "../person/service"; -import { surveyCache } from "../survey/cache"; +import { getIsPersonMonthlyActive } from "../person/service"; import { formatDateFields } from "../utils/datetime"; import { validateInputs } from "../utils/validate"; import { actionCache } from "./cache"; @@ -127,13 +126,6 @@ export const createAction = async (data: TActionInput): Promise => { actionType = "automatic"; } - let person = await getPersonByUserId(environmentId, userId); - - if (!person) { - // create person if it does not exist - person = await createPerson(environmentId, userId); - } - let actionClass = await getActionClassByEnvironmentIdAndName(environmentId, name); if (!actionClass) { @@ -148,7 +140,10 @@ export const createAction = async (data: TActionInput): Promise => { data: { person: { connect: { - id: person.id, + environmentId_userId: { + environmentId, + userId, + }, }, }, actionClass: { @@ -159,18 +154,14 @@ export const createAction = async (data: TActionInput): Promise => { }, }); - const isPersonMonthlyActive = await getIsPersonMonthlyActive(person.id); + const isPersonMonthlyActive = await getIsPersonMonthlyActive(action.personId); if (!isPersonMonthlyActive) { - activePersonCache.revalidate({ id: person.id }); + activePersonCache.revalidate({ id: action.personId }); } actionCache.revalidate({ environmentId, - personId: person.id, - }); - - surveyCache.revalidate({ - environmentId, + personId: action.personId, }); return { diff --git a/packages/lib/person/cache.ts b/packages/lib/person/cache.ts index bc1cbcb0ab..ff0fa0635f 100644 --- a/packages/lib/person/cache.ts +++ b/packages/lib/person/cache.ts @@ -23,13 +23,13 @@ export const personCache = { revalidateTag(this.tag.byId(id)); } - if (environmentId && userId) { - revalidateTag(this.tag.byEnvironmentIdAndUserId(environmentId, userId)); - } - if (environmentId) { revalidateTag(this.tag.byEnvironmentId(environmentId)); } + + if (environmentId && userId) { + revalidateTag(this.tag.byEnvironmentIdAndUserId(environmentId, userId)); + } }, }; diff --git a/packages/lib/survey/service.ts b/packages/lib/survey/service.ts index 0a8cb26151..2ef2a4ab45 100644 --- a/packages/lib/survey/service.ts +++ b/packages/lib/survey/service.ts @@ -754,12 +754,13 @@ export const getSyncSurveys = async ( const surveys = await unstable_cache( async () => { const product = await getProductByEnvironmentId(environmentId); - const person = personId === "legacy" ? ({ id: "legacy" } as TPerson) : await getPerson(personId); if (!product) { throw new Error("Product not found"); } + const person = personId === "legacy" ? ({ id: "legacy" } as TPerson) : await getPerson(personId); + if (!person) { throw new Error("Person not found"); } @@ -769,6 +770,11 @@ export const getSyncSurveys = async ( // filtered surveys for running and web surveys = surveys.filter((survey) => survey.status === "inProgress" && survey.type === "web"); + // if no surveys are left, return an empty array + if (surveys.length === 0) { + return []; + } + const displays = await getDisplaysByPersonId(person.id); // filter surveys that meet the displayOption criteria @@ -806,6 +812,11 @@ export const getSyncSurveys = async ( } }); + // if no surveys are left, return an empty array + if (surveys.length === 0) { + return []; + } + // if no surveys have segment filters, return the surveys if (!anySurveyHasFilters(surveys)) { return surveys; diff --git a/packages/lib/team/service.ts b/packages/lib/team/service.ts index 205564ca98..c929fe072b 100644 --- a/packages/lib/team/service.ts +++ b/packages/lib/team/service.ts @@ -339,7 +339,6 @@ export const getMonthlyActiveTeamPeopleCount = async (teamId: string): Promise