- This is a code action. Please make changes in your code base.
-
-
-
(
-
-
-
-
- Page URL
-
-
-
-
-
- Inner Text
-
-
-
-
-
- CSS Selector
-
-
-
- )}
- />
- {(watch("noCodeConfig.type") === "pageUrl" || !watch("noCodeConfig.type")) && (
- <>
-
-
- URL
- (
- {
- setMatchType(e as MatchType);
- setIsMatch("default");
- }} */
- {...field}>
-
-
-
-
- Exactly matches
- Contains
- Starts with
- Ends with
- Does not exactly match
- Does not contain
-
-
- )}
- />
-
-
-
-
-
-
-
-
-
Test Your URL
-
-
- Enter a URL to see if it matches your event URL
-
-
- {
- setTestUrl(e.target.value);
- setIsMatch("default");
- }}
- className={clsx(
- isMatch === "yes"
- ? "border-green-500 bg-green-50"
- : isMatch === "no"
- ? "border-red-200 bg-red-50"
- : isMatch === "default"
- ? "border-slate-200 bg-white"
- : null
- )}
- placeholder="Paste the URL you want the event to trigger on"
- />
- {
- handleMatchClick();
- }}>
- Test Match
-
-
-
-
- >
- )}
- {watch("noCodeConfig.type") === "innerHtml" && (
-
- )}
- {watch("noCodeConfig.type") === "cssSelector" && (
-
- )}
-
+ {actionClass.type === "code" ? (
+
+ This is a code action. Please make changes in your code base.
+
+ ) : actionClass.type === "noCode" ? (
+ <>
+
+ Select By
- ) : actionClass.type === "automatic" ? (
-
- This action was created automatically. You cannot make changes to it.
-
- ) : null}
-
+ This action was created automatically. You cannot make changes to it.
+
{actionClass.type !== "automatic" && (
@@ -287,7 +179,7 @@ export default function ActionSettingsTab({ environmentId, actionClass, setOpen
)}
-
+
Read Docs
diff --git a/apps/web/app/(app)/environments/[environmentId]/(actionsAndAttributes)/actions/AddNoCodeActionModal.tsx b/apps/web/app/(app)/environments/[environmentId]/(actionsAndAttributes)/actions/AddNoCodeActionModal.tsx
index 28055b32d8..086ca8aeea 100644
--- a/apps/web/app/(app)/environments/[environmentId]/(actionsAndAttributes)/actions/AddNoCodeActionModal.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/(actionsAndAttributes)/actions/AddNoCodeActionModal.tsx
@@ -1,27 +1,18 @@
"use client";
import Modal from "@/components/shared/Modal";
-import {
- Button,
- Input,
- Label,
- RadioGroup,
- RadioGroupItem,
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@formbricks/ui";
+import { Button, Input, Label } from "@formbricks/ui";
import { CursorArrowRaysIcon } from "@heroicons/react/24/solid";
-import clsx from "clsx";
import { useState } from "react";
-import { Controller, useForm } from "react-hook-form";
+import { useForm } from "react-hook-form";
import toast from "react-hot-toast";
import { testURLmatch } from "./testURLmatch";
import { createActionClass } from "@formbricks/lib/services/actionClass";
import { TActionClassInput, TActionClassNoCodeConfig } from "@formbricks/types/v1/actionClasses";
import { useRouter } from "next/navigation";
+import { CssSelector } from "@/app/(app)/environments/[environmentId]/(actionsAndAttributes)/actions/(selectors)/CssSelector";
+import { PageUrlSelector } from "@/app/(app)/environments/[environmentId]/(actionsAndAttributes)/actions/(selectors)/PageUrlSelector";
+import { InnerHtmlSelector } from "@/app/(app)/environments/[environmentId]/(actionsAndAttributes)/actions/(selectors)/InnerHtmlSelector";
interface AddNoCodeActionModalProps {
environmentId: string;
@@ -32,40 +23,30 @@ interface AddNoCodeActionModalProps {
export default function AddNoCodeActionModal({ environmentId, open, setOpen }: AddNoCodeActionModalProps) {
const router = useRouter();
const { register, control, handleSubmit, watch, reset } = useForm();
-
- // clean up noCodeConfig before submitting by removing unnecessary fields
- const filterNoCodeConfig = (noCodeConfig: TActionClassNoCodeConfig): TActionClassNoCodeConfig => {
- const { type } = noCodeConfig;
- return {
- type,
- [type]: noCodeConfig[type],
- };
- };
-
- const submitEventClass = async (data: Partial
): Promise => {
- const filteredNoCodeConfig = filterNoCodeConfig(data.noCodeConfig as TActionClassNoCodeConfig);
-
- const updatedData: TActionClassInput = {
- ...data,
- noCodeConfig: filteredNoCodeConfig,
- type: "noCode",
- } as TActionClassInput;
-
- try {
- await createActionClass(environmentId, updatedData);
- router.refresh();
- reset();
- setOpen(false);
- toast.success("Action added successfully.");
- } catch (e) {
- toast.error(e.message);
- return;
- }
- };
-
+ const [isPageUrl, setIsPageUrl] = useState(false);
+ const [isCssSelector, setIsCssSelector] = useState(false);
+ const [isInnerHtml, setIsInnerText] = useState(false);
+ const [isCreatingAction, setIsCreatingAction] = useState(false);
const [testUrl, setTestUrl] = useState("");
const [isMatch, setIsMatch] = useState("");
+ const filterNoCodeConfig = (noCodeConfig: TActionClassNoCodeConfig): TActionClassNoCodeConfig => {
+ const { pageUrl, innerHtml, cssSelector } = noCodeConfig;
+ const filteredNoCodeConfig: TActionClassNoCodeConfig = {};
+
+ if (isPageUrl && pageUrl?.rule && pageUrl?.value) {
+ filteredNoCodeConfig.pageUrl = { rule: pageUrl.rule, value: pageUrl.value };
+ }
+ if (isInnerHtml && innerHtml?.value) {
+ filteredNoCodeConfig.innerHtml = { value: innerHtml.value };
+ }
+ if (isCssSelector && cssSelector?.value) {
+ filteredNoCodeConfig.cssSelector = { value: cssSelector.value };
+ }
+
+ return filteredNoCodeConfig;
+ };
+
const handleMatchClick = () => {
const match = testURLmatch(
testUrl,
@@ -77,8 +58,47 @@ export default function AddNoCodeActionModal({ environmentId, open, setOpen }: A
if (match === "no") toast.error("Your survey would not be shown.");
};
+ const submitEventClass = async (data: Partial): Promise => {
+ try {
+ setIsCreatingAction(true);
+ if (data.name === "") throw new Error("Please give your action a name");
+ if (!isPageUrl && !isCssSelector && !isInnerHtml) throw new Error("Please select atleast one selector");
+
+ if (isPageUrl && data.noCodeConfig?.pageUrl?.rule === undefined) {
+ throw new Error("Please select a rule for page URL");
+ }
+
+ const filteredNoCodeConfig = filterNoCodeConfig(data.noCodeConfig as TActionClassNoCodeConfig);
+ const updatedData: TActionClassInput = {
+ ...data,
+ noCodeConfig: filteredNoCodeConfig,
+ type: "noCode",
+ } as TActionClassInput;
+
+ await createActionClass(environmentId, updatedData);
+ router.refresh();
+ reset();
+ resetAllStates(false);
+ toast.success("Action added successfully.");
+ } catch (e) {
+ toast.error(e.message);
+ } finally {
+ setIsCreatingAction(false);
+ }
+ };
+
+ const resetAllStates = (open: boolean) => {
+ setIsCssSelector(false);
+ setIsPageUrl(false);
+ setIsInnerText(false);
+ setTestUrl("");
+ setIsMatch("");
+ reset();
+ setOpen(open);
+ };
+
return (
-
+ resetAllStates(false)} noPadding closeOnOutsideClick={false}>
@@ -87,9 +107,9 @@ export default function AddNoCodeActionModal({ environmentId, open, setOpen }: A
-
Add Action
+
Track New User Action
- Track a user action to display surveys when it's performed.
+ Track a user action to display surveys or create user segment.
@@ -98,169 +118,49 @@ export default function AddNoCodeActionModal({ environmentId, open, setOpen }: A