mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-29 09:50:10 -06:00
fix: removes new session action (#4726)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { ACTION_TYPE_ICON_LOOKUP } from "@/app/(app)/environments/[environmentId]/actions/utils";
|
||||
import { getFormattedErrorMessage } from "@/lib/utils/helper";
|
||||
import { createActionClassAction } from "@/modules/survey/editor/actions";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
@@ -7,7 +8,6 @@ import { ErrorComponent } from "@/modules/ui/components/error-component";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
import { LoadingSpinner } from "@/modules/ui/components/loading-spinner";
|
||||
import { useTranslate } from "@tolgee/react";
|
||||
import { Code2Icon, MousePointerClickIcon, SparklesIcon } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { convertDateTimeStringShort } from "@formbricks/lib/time";
|
||||
@@ -151,15 +151,7 @@ export const ActionActivityTab = ({
|
||||
<div>
|
||||
<Label className="block text-xs font-normal text-slate-500">Type</Label>
|
||||
<div className="mt-1 flex items-center">
|
||||
<div className="mr-1.5 h-4 w-4 text-slate-600">
|
||||
{actionClass.type === "code" ? (
|
||||
<Code2Icon className="h-5 w-5" />
|
||||
) : actionClass.type === "noCode" ? (
|
||||
<MousePointerClickIcon className="h-5 w-5" />
|
||||
) : actionClass.type === "automatic" ? (
|
||||
<SparklesIcon className="h-5 w-5" />
|
||||
) : null}
|
||||
</div>
|
||||
<div className="mr-1.5 h-4 w-4 text-slate-600">{ACTION_TYPE_ICON_LOOKUP[actionClass.type]}</div>
|
||||
<p className="text-sm text-slate-700">{capitalizeFirstLetter(actionClass.type)}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -39,17 +39,23 @@ export const ActionClassesTable = ({
|
||||
<div className="rounded-xl border border-slate-200 bg-white shadow-sm">
|
||||
{TableHeading}
|
||||
<div id="actionClassesWrapper" className="flex flex-col">
|
||||
{actionClasses.map((actionClass, index) => (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
handleOpenActionDetailModalClick(e, actionClass);
|
||||
}}
|
||||
className="w-full"
|
||||
title={actionClass.name}
|
||||
key={actionClass.id}>
|
||||
{actionRows[index]}
|
||||
</button>
|
||||
))}
|
||||
{actionClasses.length > 0 ? (
|
||||
actionClasses.map((actionClass, index) => (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
handleOpenActionDetailModalClick(e, actionClass);
|
||||
}}
|
||||
className="w-full"
|
||||
title={actionClass.name}
|
||||
key={actionClass.id}>
|
||||
{actionRows[index]}
|
||||
</button>
|
||||
))
|
||||
) : (
|
||||
<div className="py-8 text-center">
|
||||
<span className="text-sm text-slate-500">No actions found</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{activeActionClass && (
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { ACTION_TYPE_ICON_LOOKUP } from "@/app/(app)/environments/[environmentId]/actions/utils";
|
||||
import { ModalWithTabs } from "@/modules/ui/components/modal-with-tabs";
|
||||
import { useTranslate } from "@tolgee/react";
|
||||
import { Code2Icon, MousePointerClickIcon, SparklesIcon } from "lucide-react";
|
||||
import { TActionClass } from "@formbricks/types/action-classes";
|
||||
import { TEnvironment } from "@formbricks/types/environment";
|
||||
import { ActionActivityTab } from "./ActionActivityTab";
|
||||
@@ -65,15 +65,7 @@ export const ActionDetailModal = ({
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
tabs={tabs}
|
||||
icon={
|
||||
actionClass.type === "code" ? (
|
||||
<Code2Icon className="h-5 w-5" />
|
||||
) : actionClass.type === "noCode" ? (
|
||||
<MousePointerClickIcon className="h-5 w-5" />
|
||||
) : actionClass.type === "automatic" ? (
|
||||
<SparklesIcon className="h-5 w-5" />
|
||||
) : null
|
||||
}
|
||||
icon={ACTION_TYPE_ICON_LOOKUP[actionClass.type]}
|
||||
label={actionClass.name}
|
||||
description={actionClass.description || ""}
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Code2Icon, MousePointerClickIcon, SparklesIcon } from "lucide-react";
|
||||
import { ACTION_TYPE_ICON_LOOKUP } from "@/app/(app)/environments/[environmentId]/actions/utils";
|
||||
import { timeSince } from "@formbricks/lib/time";
|
||||
import { TActionClass } from "@formbricks/types/action-classes";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
@@ -15,13 +15,7 @@ export const ActionClassDataRow = ({
|
||||
<div className="col-span-4 flex items-center pl-6 text-sm">
|
||||
<div className="flex items-center">
|
||||
<div className="h-5 w-5 flex-shrink-0 text-slate-500">
|
||||
{actionClass.type === "code" ? (
|
||||
<Code2Icon className="h-5 w-5" />
|
||||
) : actionClass.type === "noCode" ? (
|
||||
<MousePointerClickIcon className="h-5 w-5" />
|
||||
) : actionClass.type === "automatic" ? (
|
||||
<SparklesIcon className="h-5 w-5" />
|
||||
) : null}
|
||||
{ACTION_TYPE_ICON_LOOKUP[actionClass.type]}
|
||||
</div>
|
||||
<div className="ml-4 text-left">
|
||||
<div className="font-medium text-slate-900">{actionClass.name}</div>
|
||||
|
||||
@@ -156,7 +156,7 @@ export const ActionSettingsTab = ({
|
||||
{...field}
|
||||
placeholder={t("environments.actions.eg_clicked_download")}
|
||||
isInvalid={!!error?.message}
|
||||
disabled={actionClass.type === "automatic" || isReadOnly ? true : false}
|
||||
disabled={isReadOnly}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@@ -183,7 +183,7 @@ export const ActionSettingsTab = ({
|
||||
{...field}
|
||||
placeholder={t("environments.actions.user_clicked_download_button")}
|
||||
value={field.value ?? ""}
|
||||
disabled={actionClass.type === "automatic" || isReadOnly ? true : false}
|
||||
disabled={isReadOnly}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
@@ -212,7 +212,7 @@ export const ActionSettingsTab = ({
|
||||
|
||||
<div className="flex justify-between border-t border-slate-200 py-6">
|
||||
<div>
|
||||
{!isReadOnly && actionClass.type !== "automatic" && (
|
||||
{!isReadOnly ? (
|
||||
<Button
|
||||
type="button"
|
||||
variant="destructive"
|
||||
@@ -222,7 +222,7 @@ export const ActionSettingsTab = ({
|
||||
<TrashIcon />
|
||||
{t("common.delete")}
|
||||
</Button>
|
||||
)}
|
||||
) : null}
|
||||
|
||||
<Button variant="secondary" asChild>
|
||||
<Link href="https://formbricks.com/docs/actions/no-code" target="_blank">
|
||||
@@ -231,13 +231,13 @@ export const ActionSettingsTab = ({
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{!isReadOnly && actionClass.type !== "automatic" && (
|
||||
{!isReadOnly ? (
|
||||
<div className="flex space-x-2">
|
||||
<Button type="submit" loading={isUpdatingAction}>
|
||||
{t("common.save_changes")}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
) : null}
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { Code2Icon, MousePointerClickIcon } from "lucide-react";
|
||||
|
||||
export const ACTION_TYPE_ICON_LOOKUP = {
|
||||
code: <Code2Icon className="h-4 w-4" />,
|
||||
noCode: <MousePointerClickIcon className="h-4 w-4" />,
|
||||
};
|
||||
@@ -91,9 +91,6 @@ export const DELETE = async (
|
||||
if (!actionClass) {
|
||||
return responses.notFoundResponse("Action Class", params.actionClassId);
|
||||
}
|
||||
if (actionClass.type === "automatic") {
|
||||
return responses.badRequestResponse("Automatic action classes cannot be deleted");
|
||||
}
|
||||
const deletedActionClass = await deleteActionClass(params.actionClassId);
|
||||
return responses.successResponse(deletedActionClass);
|
||||
} catch (error) {
|
||||
|
||||
@@ -4,8 +4,8 @@ import { authenticatedActionClient } from "@/lib/utils/action-client";
|
||||
import { checkAuthorizationUpdated } from "@/lib/utils/action-client-middleware";
|
||||
import { getOrganizationIdFromEnvironmentId, getProjectIdFromEnvironmentId } from "@/lib/utils/helper";
|
||||
import { checkMultiLanguagePermission } from "@/modules/ee/multi-language-surveys/lib/actions";
|
||||
import { getSurveyFollowUpsPermission } from "@/modules/survey/follow-ups/lib/utils";
|
||||
import { createSurvey } from "@/modules/survey/components/template-list/lib/survey";
|
||||
import { getSurveyFollowUpsPermission } from "@/modules/survey/follow-ups/lib/utils";
|
||||
import { getOrganizationBilling } from "@/modules/survey/lib/survey";
|
||||
import { z } from "zod";
|
||||
import { OperationNotAllowedError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
|
||||
@@ -10,8 +10,9 @@ import {
|
||||
getProjectIdFromSurveyId,
|
||||
} from "@/lib/utils/helper";
|
||||
import { checkMultiLanguagePermission } from "@/modules/ee/multi-language-surveys/lib/actions";
|
||||
import { getSurveyFollowUpsPermission } from "@/modules/survey/follow-ups/lib/utils";
|
||||
import { createActionClass } from "@/modules/survey/editor/lib/action-class";
|
||||
import { updateSurvey } from "@/modules/survey/editor/lib/survey";
|
||||
import { getSurveyFollowUpsPermission } from "@/modules/survey/follow-ups/lib/utils";
|
||||
import { getOrganizationBilling } from "@/modules/survey/lib/survey";
|
||||
import { z } from "zod";
|
||||
import { UNSPLASH_ACCESS_KEY, UNSPLASH_ALLOWED_DOMAINS } from "@formbricks/lib/constants";
|
||||
@@ -19,7 +20,6 @@ import { ZActionClassInput } from "@formbricks/types/action-classes";
|
||||
import { OperationNotAllowedError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { ZSurvey } from "@formbricks/types/surveys/types";
|
||||
import { getProject } from "./lib/project";
|
||||
import { createActionClass } from "@/modules/survey/editor/lib/action-class";
|
||||
|
||||
/**
|
||||
* Checks if survey follow-ups are enabled for the given organization.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { ACTION_TYPE_ICON_LOOKUP } from "@/app/(app)/environments/[environmentId]/actions/utils";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
import { ActionClass } from "@prisma/client";
|
||||
import { useTranslate } from "@tolgee/react";
|
||||
import { Code2Icon, MousePointerClickIcon, SparklesIcon } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
|
||||
@@ -28,7 +28,6 @@ export const SavedActionsTab = ({
|
||||
|
||||
const codeActions = filteredActionClasses.filter((actionClass) => actionClass.type === "code");
|
||||
const noCodeActions = filteredActionClasses.filter((actionClass) => actionClass.type === "noCode");
|
||||
const automaticActions = filteredActionClasses.filter((actionClass) => actionClass.type === "automatic");
|
||||
|
||||
const handleActionClick = (action: ActionClass) => {
|
||||
setLocalSurvey((prev) => ({
|
||||
@@ -38,6 +37,8 @@ export const SavedActionsTab = ({
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const allActions = [...noCodeActions, ...codeActions];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Input
|
||||
@@ -54,12 +55,17 @@ export const SavedActionsTab = ({
|
||||
id="search-actions"
|
||||
/>
|
||||
<div className="max-h-96 overflow-y-auto">
|
||||
{[automaticActions, noCodeActions, codeActions].map(
|
||||
{!allActions.length && (
|
||||
<div className="pt-4 text-center">
|
||||
<span className="text-sm text-slate-500">No saved actions found</span>
|
||||
</div>
|
||||
)}
|
||||
{[noCodeActions, codeActions].map(
|
||||
(actions, i) =>
|
||||
actions.length > 0 && (
|
||||
<div key={i} className="me-4">
|
||||
<h2 className="mb-2 mt-4 font-semibold">
|
||||
{i === 0 ? t("common.automatic") : i === 1 ? t("common.no_code") : t("common.code")}
|
||||
{i === 0 ? t("common.no_code") : t("common.code")}
|
||||
</h2>
|
||||
<div className="flex flex-col gap-2">
|
||||
{actions.map((action) => (
|
||||
@@ -69,15 +75,8 @@ export const SavedActionsTab = ({
|
||||
onClick={() => handleActionClick(action)}>
|
||||
<div className="mt-1 flex items-center">
|
||||
<div className="mr-1.5 h-4 w-4 text-slate-600">
|
||||
{action.type === "code" ? (
|
||||
<Code2Icon className="h-4 w-4" />
|
||||
) : action.type === "noCode" ? (
|
||||
<MousePointerClickIcon className="h-4 w-4" />
|
||||
) : action.type === "automatic" ? (
|
||||
<SparklesIcon className="h-4 w-4" />
|
||||
) : null}
|
||||
{ACTION_TYPE_ICON_LOOKUP[action.type]}
|
||||
</div>
|
||||
|
||||
<h4 className="text-sm font-semibold text-slate-600">{action.name}</h4>
|
||||
</div>
|
||||
<p className="mt-1 text-xs text-slate-500">{action.description}</p>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { TTeamPermission } from "@/modules/ee/teams/project-teams/types/team";
|
||||
import { FollowUpsView } from "@/modules/survey/follow-ups/components/follow-ups-view";
|
||||
import { LoadingSkeleton } from "@/modules/survey/editor/components/loading-skeleton";
|
||||
import { QuestionsView } from "@/modules/survey/editor/components/questions-view";
|
||||
import { SettingsView } from "@/modules/survey/editor/components/settings-view";
|
||||
import { StylingView } from "@/modules/survey/editor/components/styling-view";
|
||||
import { SurveyEditorTabs } from "@/modules/survey/editor/components/survey-editor-tabs";
|
||||
import { SurveyMenuBar } from "@/modules/survey/editor/components/survey-menu-bar";
|
||||
import { FollowUpsView } from "@/modules/survey/follow-ups/components/follow-ups-view";
|
||||
import { PreviewSurvey } from "@/modules/ui/components/preview-survey";
|
||||
import { ActionClass, Environment, Language, OrganizationRole, Project } from "@prisma/client";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { ACTION_TYPE_ICON_LOOKUP } from "@/app/(app)/environments/[environmentId]/actions/utils";
|
||||
import { TTeamPermission } from "@/modules/ee/teams/project-teams/types/team";
|
||||
import { getTeamPermissionFlags } from "@/modules/ee/teams/utils/teams";
|
||||
import { AddActionModal } from "@/modules/survey/editor/components/add-action-modal";
|
||||
@@ -10,14 +11,7 @@ import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { ActionClass, OrganizationRole } from "@prisma/client";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { useTranslate } from "@tolgee/react";
|
||||
import {
|
||||
CheckIcon,
|
||||
Code2Icon,
|
||||
MousePointerClickIcon,
|
||||
PlusIcon,
|
||||
SparklesIcon,
|
||||
Trash2Icon,
|
||||
} from "lucide-react";
|
||||
import { CheckIcon, PlusIcon, Trash2Icon } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { getAccessFlags } from "@formbricks/lib/membership/utils";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
@@ -200,13 +194,7 @@ export const WhenToSendCard = ({
|
||||
<div>
|
||||
<div className="mt-1 flex items-center">
|
||||
<div className="mr-1.5 h-4 w-4 text-slate-600">
|
||||
{trigger.actionClass.type === "code" ? (
|
||||
<Code2Icon className="h-4 w-4" />
|
||||
) : trigger.actionClass.type === "noCode" ? (
|
||||
<MousePointerClickIcon className="h-4 w-4" />
|
||||
) : trigger.actionClass.type === "automatic" ? (
|
||||
<SparklesIcon className="h-4 w-4" />
|
||||
) : null}
|
||||
{ACTION_TYPE_ICON_LOOKUP[trigger.actionClass.type]}
|
||||
</div>
|
||||
|
||||
<h4 className="text-sm font-semibold text-slate-600">{trigger.actionClass.name}</h4>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ActionClass, Prisma } from "@prisma/client";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { actionClassCache } from "@formbricks/lib/actionClass/cache";
|
||||
import { DatabaseError } from "@formbricks/types/errors";
|
||||
import { TActionClassInput } from "@formbricks/types/action-classes";
|
||||
import { DatabaseError } from "@formbricks/types/errors";
|
||||
|
||||
export const createActionClass = async (
|
||||
environmentId: string,
|
||||
@@ -36,4 +36,4 @@ export const createActionClass = async (
|
||||
|
||||
throw new DatabaseError(`Database error when creating an action for environment ${environmentId}`);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,9 +4,9 @@ import { getSegments } from "@/modules/ee/contacts/segments/lib/segments";
|
||||
import { getIsContactsEnabled, getMultiLanguagePermission } from "@/modules/ee/license-check/lib/utils";
|
||||
import { getProjectPermissionByUserId } from "@/modules/ee/teams/lib/roles";
|
||||
import { getTeamPermissionFlags } from "@/modules/ee/teams/utils/teams";
|
||||
import { getSurveyFollowUpsPermission } from "@/modules/survey/follow-ups/lib/utils";
|
||||
import { getProjectLanguages } from "@/modules/survey/editor/lib/project";
|
||||
import { getUserEmail } from "@/modules/survey/editor/lib/user";
|
||||
import { getSurveyFollowUpsPermission } from "@/modules/survey/follow-ups/lib/utils";
|
||||
import { getActionClasses } from "@/modules/survey/lib/action-class";
|
||||
import { getEnvironment } from "@/modules/survey/lib/environment";
|
||||
import { getMembershipRoleByUserIdOrganizationId } from "@/modules/survey/lib/membership";
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import FollowUpActionMultiEmailInput from "@/modules/survey/follow-ups/components/follow-up-action-multi-email-input";
|
||||
import { getSurveyFollowUpActionDefaultBody } from "@/modules/survey/editor/lib/utils";
|
||||
import {
|
||||
TCreateSurveyFollowUpForm,
|
||||
ZCreateSurveyFollowUpFormSchema,
|
||||
} from "@/modules/survey/editor/types/survey-follow-up";
|
||||
import FollowUpActionMultiEmailInput from "@/modules/survey/follow-ups/components/follow-up-action-multi-email-input";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Checkbox } from "@/modules/ui/components/checkbox";
|
||||
import { Editor } from "@/modules/ui/components/editor";
|
||||
@@ -588,9 +588,9 @@ export const FollowUpModal = ({
|
||||
<div className="h-4 w-4">
|
||||
{
|
||||
QUESTIONS_ICON_MAP[
|
||||
option.type === "openTextQuestion"
|
||||
? "openText"
|
||||
: "contactInfo"
|
||||
option.type === "openTextQuestion"
|
||||
? "openText"
|
||||
: "contactInfo"
|
||||
]
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { getFormattedErrorMessage } from "@/lib/utils/helper";
|
||||
import {
|
||||
isSurveyResponsePresentAction,
|
||||
sendLinkSurveyEmailAction,
|
||||
} from "@/modules/survey/link/actions";
|
||||
import { isSurveyResponsePresentAction, sendLinkSurveyEmailAction } from "@/modules/survey/link/actions";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { FormControl, FormError, FormField, FormItem } from "@/modules/ui/components/form";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
|
||||
@@ -113,16 +113,16 @@ export const getSurveysSortedByRelevance = reactCache(
|
||||
offset && offset > inProgressSurveyCount
|
||||
? []
|
||||
: await prisma.survey.findMany({
|
||||
where: {
|
||||
environmentId,
|
||||
status: "inProgress",
|
||||
...buildWhereClause(filterCriteria),
|
||||
},
|
||||
select: surveySelect,
|
||||
orderBy: buildOrderByClause("updatedAt"),
|
||||
take: limit,
|
||||
skip: offset,
|
||||
});
|
||||
where: {
|
||||
environmentId,
|
||||
status: "inProgress",
|
||||
...buildWhereClause(filterCriteria),
|
||||
},
|
||||
select: surveySelect,
|
||||
orderBy: buildOrderByClause("updatedAt"),
|
||||
take: limit,
|
||||
skip: offset,
|
||||
});
|
||||
|
||||
surveys = inProgressSurveys.map((survey) => {
|
||||
return {
|
||||
@@ -394,23 +394,23 @@ export const copySurveyToOtherEnvironment = async (
|
||||
hiddenFields: structuredClone(existingSurvey.hiddenFields),
|
||||
languages: hasLanguages
|
||||
? {
|
||||
create: existingSurvey.languages.map((surveyLanguage) => ({
|
||||
language: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
projectId_code: { code: surveyLanguage.language.code, projectId: targetProject.id },
|
||||
},
|
||||
create: {
|
||||
code: surveyLanguage.language.code,
|
||||
alias: surveyLanguage.language.alias,
|
||||
projectId: targetProject.id,
|
||||
create: existingSurvey.languages.map((surveyLanguage) => ({
|
||||
language: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
projectId_code: { code: surveyLanguage.language.code, projectId: targetProject.id },
|
||||
},
|
||||
create: {
|
||||
code: surveyLanguage.language.code,
|
||||
alias: surveyLanguage.language.alias,
|
||||
projectId: targetProject.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
default: surveyLanguage.default,
|
||||
enabled: surveyLanguage.enabled,
|
||||
})),
|
||||
}
|
||||
default: surveyLanguage.default,
|
||||
enabled: surveyLanguage.enabled,
|
||||
})),
|
||||
}
|
||||
: undefined,
|
||||
triggers: {
|
||||
create: existingSurvey.triggers.map((trigger): Prisma.SurveyTriggerCreateWithoutSurveyInput => {
|
||||
|
||||
@@ -217,6 +217,9 @@ test.describe("Survey Create & Submit Response without logic", async () => {
|
||||
});
|
||||
|
||||
test.describe("Multi Language Survey Create", async () => {
|
||||
// 4 minutes
|
||||
test.setTimeout(1000 * 60 * 4);
|
||||
|
||||
test("Create Survey", async ({ page, users }) => {
|
||||
const user = await users.create();
|
||||
await user.login();
|
||||
@@ -602,7 +605,7 @@ test.describe("Multi Language Survey Create", async () => {
|
||||
|
||||
await page.getByRole("button", { name: "Publish" }).click();
|
||||
|
||||
// await page.waitForURL(/\/environments\/[^/]+\/surveys\/[^/]+\/summary$/);
|
||||
await page.waitForTimeout(5000);
|
||||
await page.waitForURL(/\/environments\/[^/]+\/surveys\/[^/]+\/summary(\?.*)?$/);
|
||||
await page.getByLabel("Select Language").click();
|
||||
await page.getByText("German").click();
|
||||
@@ -613,7 +616,8 @@ test.describe("Multi Language Survey Create", async () => {
|
||||
});
|
||||
|
||||
test.describe("Testing Survey with advanced logic", async () => {
|
||||
test.setTimeout(300000);
|
||||
// 6 minutes
|
||||
test.setTimeout(1000 * 60 * 6);
|
||||
let url: string | null;
|
||||
|
||||
test("Create survey and submit response", async ({ page, users }) => {
|
||||
@@ -869,13 +873,14 @@ test.describe("Testing Survey with advanced logic", async () => {
|
||||
await page.waitForURL(/\/environments\/[^/]+\/surveys\/[^/]+\/summary(\?.*)?$/);
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await page.getByRole("button", { name: "Close" }).click();
|
||||
await page.getByRole("link").filter({ hasText: "Responses" }).click();
|
||||
await page.waitForSelector("#response-table");
|
||||
|
||||
await expect(page.getByRole("cell", { name: "score" })).toBeVisible();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.waitForTimeout(5000);
|
||||
await expect(page.getByRole("cell", { name: "32", exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
152
docs/mint.json
152
docs/mint.json
@@ -399,54 +399,54 @@
|
||||
"source": "/docs/link-surveys/verify-email-before-survey"
|
||||
},
|
||||
{
|
||||
"source": "/docs/app-surveys/global/add-image-or-video-question",
|
||||
"destination": "/docs/xm-and-surveys/surveys/general-features/add-image-or-video-question",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/surveys/general-features/add-image-or-video-question"
|
||||
"source": "/docs/app-surveys/global/add-image-or-video-question"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/consent",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/consent",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/consent"
|
||||
"source": "/docs/core-features/global/question-type/consent"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/statement-cta",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/statement-cta",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/statement-cta"
|
||||
"source": "/docs/core-features/global/question-type/statement-cta"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/integrations/airtable",
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/airtable",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/airtable"
|
||||
"source": "/docs/developer-docs/integrations/airtable"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/integrations/zapier",
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/zapier",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/zapier"
|
||||
"source": "/docs/developer-docs/integrations/zapier"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/integrations/wordpress",
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/wordpress",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/wordpress"
|
||||
"source": "/docs/developer-docs/integrations/wordpress"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/integrations/slack",
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/slack",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/slack"
|
||||
"source": "/docs/developer-docs/integrations/slack"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/integrations/n8n",
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/n8n",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/n8n"
|
||||
"source": "/docs/developer-docs/integrations/n8n"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/integrations/notion",
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/notion",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/notion"
|
||||
"source": "/docs/developer-docs/integrations/notion"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/integrations/google-sheets",
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/google-sheets",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/google-sheets"
|
||||
"source": "/docs/developer-docs/integrations/google-sheets"
|
||||
},
|
||||
{
|
||||
"destination": "/docs/xm-and-surveys/surveys/website-app-surveys/quickstart",
|
||||
@@ -509,54 +509,54 @@
|
||||
"source": "/docs/self-hosting/migration-guide"
|
||||
},
|
||||
{
|
||||
"source": "/docs/self-hosting/integrations",
|
||||
"destination": "/docs/self-hosting/configuration/integrations",
|
||||
"permanent": true,
|
||||
"destination": "/docs/self-hosting/configuration/integrations"
|
||||
"source": "/docs/self-hosting/integrations"
|
||||
},
|
||||
{
|
||||
"source": "/docs/self-hosting/license",
|
||||
"destination": "/docs/self-hosting/advanced/license",
|
||||
"permanent": true,
|
||||
"destination": "/docs/self-hosting/advanced/license"
|
||||
"source": "/docs/self-hosting/license"
|
||||
},
|
||||
{
|
||||
"source": "/docs/self-hosting/rate-limiting",
|
||||
"destination": "/docs/self-hosting/advanced/rate-limiting",
|
||||
"permanent": true,
|
||||
"destination": "/docs/self-hosting/advanced/rate-limiting"
|
||||
"source": "/docs/self-hosting/rate-limiting"
|
||||
},
|
||||
{
|
||||
"source": "/docs/self-hosting/kubernetes",
|
||||
"destination": "/docs/self-hosting/setup/cluster-setup",
|
||||
"permanent": true,
|
||||
"destination": "/docs/self-hosting/setup/cluster-setup"
|
||||
"source": "/docs/self-hosting/kubernetes"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/overview",
|
||||
"destination": "/docs/development/overview",
|
||||
"permanent": true,
|
||||
"destination": "/docs/development/overview"
|
||||
"source": "/docs/developer-docs/overview"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/js-sdk",
|
||||
"destination": "/docs/xm-and-surveys/surveys/website-app-surveys/framework-guides",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/surveys/website-app-surveys/framework-guides"
|
||||
"source": "/docs/developer-docs/js-sdk"
|
||||
},
|
||||
{
|
||||
"source": "docs/developer-docs/react-native-in-app-surveys",
|
||||
"destination": "/docs/xm-and-surveys/surveys/website-app-surveys/framework-guides#react-native",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/surveys/website-app-surveys/framework-guides#react-native"
|
||||
"source": "docs/developer-docs/react-native-in-app-surveys"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/rest-api",
|
||||
"destination": "/docs/api-reference/rest-api",
|
||||
"permanent": true,
|
||||
"destination": "/docs/api-reference/rest-api"
|
||||
"source": "/docs/developer-docs/rest-api"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/webhooks",
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/webhooks",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/webhooks"
|
||||
"source": "/docs/developer-docs/webhooks"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/contributing/get-started",
|
||||
"destination": "/docs/development/contribution/contribution",
|
||||
"permanent": true,
|
||||
"destination": "/docs/development/contribution/contribution"
|
||||
"source": "/docs/developer-docs/contributing/get-started"
|
||||
},
|
||||
{
|
||||
"destination": "/docs/xm-and-surveys/surveys/website-app-surveys/actions",
|
||||
@@ -589,94 +589,94 @@
|
||||
"source": "/docs/app-surveys/global/metadata"
|
||||
},
|
||||
{
|
||||
"source": "/docs/api-docs",
|
||||
"destination": "/docs/api-reference",
|
||||
"permanent": true,
|
||||
"destination": "/docs/api-reference"
|
||||
"source": "/docs/api-docs"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/contributing/troubleshooting",
|
||||
"destination": "/docs/development/troubleshooting",
|
||||
"permanent": true,
|
||||
"destination": "/docs/development/troubleshooting"
|
||||
"source": "/docs/developer-docs/contributing/troubleshooting"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/file-upload",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/file-upload",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/file-upload"
|
||||
"source": "/docs/core-features/global/question-type/file-upload"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/picture-selection",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/select-picture",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/select-picture"
|
||||
"source": "/docs/core-features/global/question-type/picture-selection"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/rating",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/rating",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/rating"
|
||||
"source": "/docs/core-features/global/question-type/rating"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/date",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/date",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/date"
|
||||
"source": "/docs/core-features/global/question-type/date"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/schedule",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/schedule-a-meeting",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/schedule-a-meeting"
|
||||
"source": "/docs/core-features/global/question-type/schedule"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/free-text",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/free-text",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/free-text"
|
||||
"source": "/docs/core-features/global/question-type/free-text"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/single-select",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/select-single",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/select-single"
|
||||
"source": "/docs/core-features/global/question-type/single-select"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/multiple-select",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/select-multiple",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/select-multiple"
|
||||
"source": "/docs/core-features/global/question-type/multiple-select"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/matrix",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/matrix",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/matrix"
|
||||
"source": "/docs/core-features/global/question-type/matrix"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/integrations/make",
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/make",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/make"
|
||||
"source": "/docs/developer-docs/integrations/make"
|
||||
},
|
||||
{
|
||||
"source": "/docs/developer-docs/integrations/overview",
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/overview",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/integrations/overview"
|
||||
"source": "/docs/developer-docs/integrations/overview"
|
||||
},
|
||||
{
|
||||
"source": "/docs/app-surveys/global/hidden-fields",
|
||||
"destination": "/docs/xm-and-surveys/surveys/general-features/hidden-fields",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/surveys/general-features/hidden-fields"
|
||||
"source": "/docs/app-surveys/global/hidden-fields"
|
||||
},
|
||||
{
|
||||
"source": "/docs/app-surveys/global/limit-submissions",
|
||||
"destination": "/docs/xm-and-surveys/surveys/general-features/limit-submissions",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/surveys/general-features/limit-submissions"
|
||||
"source": "/docs/app-surveys/global/limit-submissions"
|
||||
},
|
||||
{
|
||||
"source": "/docs/core-features/global/question-type/net-promoter-score",
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/net-promoter-score",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/core-features/question-type/net-promoter-score"
|
||||
"source": "/docs/core-features/global/question-type/net-promoter-score"
|
||||
},
|
||||
{
|
||||
"source": "/docs/link-surveys/data-prefilling",
|
||||
"destination": "/docs/xm-and-surveys/surveys/link-surveys/data-prefilling",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/surveys/link-surveys/data-prefilling"
|
||||
"source": "/docs/link-surveys/data-prefilling"
|
||||
},
|
||||
{
|
||||
"source": "/docs/app-surveys/global/multi-language-surveys",
|
||||
"destination": "/docs/xm-and-surveys/surveys/general-features/multi-language-surveys",
|
||||
"permanent": true,
|
||||
"destination": "/docs/xm-and-surveys/surveys/general-features/multi-language-surveys"
|
||||
"source": "/docs/app-surveys/global/multi-language-surveys"
|
||||
}
|
||||
],
|
||||
"tabs": [
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import type { MigrationScript } from "../../src/scripts/migration-runner";
|
||||
|
||||
export const removedNewSessionEvent: MigrationScript = {
|
||||
type: "data",
|
||||
id: "dnh52k9vepinuhwuur8fclqf",
|
||||
name: "20250211050118_removed_new_session_event",
|
||||
run: async ({ tx }) => {
|
||||
// Find all automatic actions - these are all the "New Session" actions
|
||||
const automaticActionsResult = await tx.$queryRaw`
|
||||
SELECT id, name
|
||||
FROM "ActionClass"
|
||||
WHERE type = 'automatic'
|
||||
`;
|
||||
|
||||
const automaticActions = automaticActionsResult as { id: string; name: string }[];
|
||||
|
||||
console.log(`Found ${automaticActions.length.toString()} new session actions`);
|
||||
|
||||
const actionsToUpdate = [];
|
||||
const actionsToDelete = [];
|
||||
|
||||
for (const action of automaticActions) {
|
||||
// Check for survey triggers using this action
|
||||
const surveyTriggersResult = await tx.$queryRaw<{ count: string }[]>`
|
||||
SELECT COUNT(*)::integer as "count"
|
||||
FROM "SurveyTrigger"
|
||||
WHERE "actionClassId" = ${action.id}
|
||||
`;
|
||||
|
||||
// Parse the count (PostgreSQL may return count as a string)
|
||||
const triggerCount = parseInt(surveyTriggersResult[0].count, 10);
|
||||
|
||||
if (triggerCount > 0) {
|
||||
actionsToUpdate.push(action.id);
|
||||
} else {
|
||||
actionsToDelete.push(action.id);
|
||||
}
|
||||
}
|
||||
|
||||
// batches:
|
||||
const batchSize = 20000;
|
||||
|
||||
for (let i = 0; i < actionsToUpdate.length; i += batchSize) {
|
||||
const batch = actionsToUpdate.slice(i, i + batchSize);
|
||||
|
||||
const updatedActions = await tx.$executeRaw`
|
||||
UPDATE "ActionClass"
|
||||
SET type = 'noCode',
|
||||
"noCodeConfig" = '{"type":"pageView","urlFilters":[]}'::jsonb
|
||||
WHERE id IN (${Prisma.join(batch)})
|
||||
`;
|
||||
|
||||
console.log(`Updated ${updatedActions.toString()} actions`);
|
||||
}
|
||||
|
||||
for (let i = 0; i < actionsToDelete.length; i += batchSize) {
|
||||
const batch = actionsToDelete.slice(i, i + batchSize);
|
||||
|
||||
const deletedActions = await tx.$executeRaw`
|
||||
DELETE FROM "ActionClass" WHERE id IN (${Prisma.join(batch)})
|
||||
`;
|
||||
|
||||
console.log(`Deleted ${deletedActions.toString()} actions`);
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- The values [automatic] on the enum `ActionType` will be removed. If these variants are still used in the database, this will fail.
|
||||
|
||||
*/
|
||||
-- AlterEnum
|
||||
BEGIN;
|
||||
CREATE TYPE "ActionType_new" AS ENUM ('code', 'noCode');
|
||||
ALTER TABLE "ActionClass" ALTER COLUMN "type" TYPE "ActionType_new" USING ("type"::text::"ActionType_new");
|
||||
ALTER TYPE "ActionType" RENAME TO "ActionType_old";
|
||||
ALTER TYPE "ActionType_new" RENAME TO "ActionType";
|
||||
DROP TYPE "ActionType_old";
|
||||
COMMIT;
|
||||
@@ -333,7 +333,6 @@ model SurveyFollowUp {
|
||||
enum ActionType {
|
||||
code
|
||||
noCode
|
||||
automatic
|
||||
}
|
||||
|
||||
model ActionClass {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { type TAttributes } from "@formbricks/types/attributes";
|
||||
import { type ApiErrorResponse } from "@formbricks/types/errors";
|
||||
import { type TJsConfig, type TJsConfigInput } from "@formbricks/types/js";
|
||||
import { trackNoCodeAction } from "./actions";
|
||||
import { updateAttributes } from "./attributes";
|
||||
import { Config } from "./config";
|
||||
import {
|
||||
@@ -359,9 +358,6 @@ export const initialize = async (
|
||||
} catch (e) {
|
||||
handleErrorOnFirstInit(e);
|
||||
}
|
||||
|
||||
// and track the new session event
|
||||
await trackNoCodeAction("New Session");
|
||||
}
|
||||
|
||||
logger.debug("Adding event listeners");
|
||||
|
||||
@@ -51,11 +51,10 @@ export const mockConfig: TConfig = {
|
||||
],
|
||||
triggers: [
|
||||
{
|
||||
// { actionClass: ActionClass }
|
||||
actionClass: {
|
||||
id: mockActionClassId,
|
||||
key: "onboardingTrigger",
|
||||
type: "code", // or "automatic"
|
||||
type: "code",
|
||||
name: "Manual Trigger",
|
||||
createdAt: "2025-01-01T10:00:00Z",
|
||||
updatedAt: "2025-01-01T10:00:00Z",
|
||||
|
||||
@@ -68,7 +68,7 @@ export const ZActionClassNoCodeConfig = z.union([
|
||||
|
||||
export type TActionClassNoCodeConfig = z.infer<typeof ZActionClassNoCodeConfig>;
|
||||
|
||||
export const ZActionClassType = z.enum(["code", "noCode", "automatic"]);
|
||||
export const ZActionClassType = z.enum(["code", "noCode"]);
|
||||
|
||||
export type TActionClassType = z.infer<typeof ZActionClassType>;
|
||||
|
||||
@@ -108,14 +108,6 @@ const ZActionClassInputNoCode = ZActionClassInputBase.extend({
|
||||
noCodeConfig: ZActionClassNoCodeConfig.nullable(),
|
||||
});
|
||||
|
||||
const ZActionClassInputAutomatic = ZActionClassInputBase.extend({
|
||||
type: z.literal("automatic"),
|
||||
});
|
||||
|
||||
export const ZActionClassInput = z.union([
|
||||
ZActionClassInputCode,
|
||||
ZActionClassInputNoCode,
|
||||
ZActionClassInputAutomatic,
|
||||
]);
|
||||
export const ZActionClassInput = z.union([ZActionClassInputCode, ZActionClassInputNoCode]);
|
||||
|
||||
export type TActionClassInput = z.infer<typeof ZActionClassInput>;
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const ZAttributeClassType = z.enum(["code", "noCode", "automatic"]);
|
||||
|
||||
export type TAttributeClassType = z.infer<typeof ZAttributeClassType>;
|
||||
|
||||
export const ZAttributeClass = z.object({
|
||||
id: z.string().cuid2(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable(),
|
||||
type: ZAttributeClassType,
|
||||
environmentId: z.string(),
|
||||
archived: z.boolean(),
|
||||
});
|
||||
|
||||
export const ZAttributeClassAutomaticInput = z.object({
|
||||
name: z.string(),
|
||||
description: z.string(),
|
||||
type: z.enum(["automatic"]),
|
||||
});
|
||||
|
||||
export const ZAttributeClassUpdateInput = z.object({
|
||||
name: z.string(),
|
||||
description: z.string().optional(),
|
||||
archived: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export type TAttributeClassAutomaticInput = z.infer<typeof ZAttributeClassAutomaticInput>;
|
||||
|
||||
export type TAttributeClassUpdateInput = z.infer<typeof ZAttributeClassUpdateInput>;
|
||||
|
||||
export type TAttributeClass = z.infer<typeof ZAttributeClass>;
|
||||
Reference in New Issue
Block a user