+
item
-
+
{showAdvanced && (
item
)}
-
- )
+
+ );
}
export default Items
diff --git a/src/components/ga4/EventBuilder/Parameter.tsx b/src/components/ga4/EventBuilder/Parameter.tsx
index a7554e5a5..5e1509780 100644
--- a/src/components/ga4/EventBuilder/Parameter.tsx
+++ b/src/components/ga4/EventBuilder/Parameter.tsx
@@ -1,16 +1,24 @@
import * as React from "react"
-import TextField from "@material-ui/core/TextField"
-import makeStyles from "@material-ui/core/styles/makeStyles"
-
+import { styled } from '@mui/material/styles';
+import TextField from "@mui/material/TextField"
import { Parameter as ParameterT } from "./types"
import { ShowAdvancedCtx } from "."
-import useFormStyles from "@/hooks/useFormStyles"
-import { IconButton, Tooltip } from "@material-ui/core"
-import { Delete } from "@material-ui/icons"
+import { IconButton, Tooltip } from "@mui/material"
+import { Delete } from "@mui/icons-material"
+
+const PREFIX = 'Parameter';
+
+const classes = {
+ parameter: `${PREFIX}-parameter`
+};
-const useStyles = makeStyles(theme => ({
- parameter: {
+const Root = styled('section')((
+ {
+ theme
+ }
+) => ({
+ [`&.${classes.parameter}`]: {
display: "flex",
"&> *": {
flexGrow: 1,
@@ -18,8 +26,8 @@ const useStyles = makeStyles(theme => ({
"&> :not(:first-child)": {
marginLeft: theme.spacing(1),
},
- },
-}))
+ }
+}));
interface Props {
parameter: ParameterT
@@ -34,15 +42,14 @@ const Parameter: React.FC
= ({
setParamValue,
removeParam,
}) => {
- const classes = useStyles()
- const formClasses = useFormStyles()
+
const showAdvanced = React.useContext(ShowAdvancedCtx)
const [name, setName] = React.useState(parameter.name)
const [value, setValue] = React.useState(parameter.value || "")
const inputs = (
-
+
= ({
label={`${parameter.type} value`}
placeholder={parameter.exampleValue?.toString()}
/>
-
+
)
if (showAdvanced) {
return (
-
+
diff --git a/src/components/ga4/EventBuilder/Parameters.tsx b/src/components/ga4/EventBuilder/Parameters.tsx
index 238ef9c6e..26274b614 100644
--- a/src/components/ga4/EventBuilder/Parameters.tsx
+++ b/src/components/ga4/EventBuilder/Parameters.tsx
@@ -1,18 +1,35 @@
import { DAB, SAB } from "@/components/Buttons"
-import useFormStyles from "@/hooks/useFormStyles"
-import makeStyles from "@material-ui/core/styles/makeStyles"
+import { styled } from '@mui/material/styles';
import * as React from "react"
import { ShowAdvancedCtx } from "."
import Parameter from "./Parameter"
import { Parameter as ParameterT } from "./types"
-const useStyles = makeStyles(theme => ({
- parameters: {
+const PREFIX = 'Parameters';
+
+const classes = {
+ buttonRow: `${PREFIX}-buttonRow`,
+ parameters: `${PREFIX}-parameters`
+};
+
+const Root = styled('section')((
+ {
+ theme
+ }
+) => ({
+ [`&.${classes.parameters}`]: {
"&> :not(:first-child)": {
marginTop: theme.spacing(1),
},
},
-}))
+
+ [`& .${classes.buttonRow}`]: {
+ display: "flex",
+ "&> *:not(:last-child)": {
+ marginRight: theme.spacing(1),
+ },
+ }
+}));
interface Props {
parameters: ParameterT[]
@@ -36,11 +53,9 @@ const Parameters: React.FC = ({
removeItem,
}) => {
const showAdvanced = React.useContext(ShowAdvancedCtx)
- const classes = useStyles()
- const formClasses = useFormStyles()
return (
-
+
{parameters.map((parameter, idx) => (
= ({
removeParam={() => removeParam(idx)}
/>
))}
-
+
{showAdvanced && (
<>
= ({
)}
{removeItem !== undefined && (
<>
-
+
item
>
)}
-
- )
+
+ );
}
export default Parameters
diff --git a/src/components/ga4/EventBuilder/ValidateEvent/handlers/formatCheckLib.ts b/src/components/ga4/EventBuilder/ValidateEvent/handlers/formatCheckLib.ts
index 18232d3e1..b6a72d53a 100644
--- a/src/components/ga4/EventBuilder/ValidateEvent/handlers/formatCheckLib.ts
+++ b/src/components/ga4/EventBuilder/ValidateEvent/handlers/formatCheckLib.ts
@@ -1,7 +1,8 @@
-import { ValidationMessage } from "../../types"
+import {ValidationMessage} from "../../types"
import 'object-sizeof'
import sizeof from "object-sizeof"
-import { eventDefinitions } from "../schemas/eventTypes/eventDefinitions"
+import {eventDefinitions} from "../schemas/eventTypes/eventDefinitions"
+import {InstanceId} from "../../types"
const RESERVED_EVENT_NAMES = [
"ad_activeview", "ad_click", "ad_exposure", "ad_impression", "ad_query",
@@ -18,7 +19,7 @@ const RESERVED_USER_PROPERTY_NAMES = [
// formatCheckLib provides additional validations for payload not included in
// the schema validations. All checks are consistent with Firebase documentation.
-export const formatCheckLib = (payload, instanceId, api_secret, useFirebase) => {
+export const formatCheckLib = (payload: any, instanceId: InstanceId, api_secret: string, useFirebase: boolean) => {
let errors: ValidationMessage[] = []
const appOrClientErrors = isValidAppOrClientId(payload, useFirebase)
@@ -33,7 +34,7 @@ export const formatCheckLib = (payload, instanceId, api_secret, useFirebase) =>
return [
...errors,
- ...appOrClientErrors,
+ ...appOrClientErrors,
...eventNameErrors,
...userPropertyNameErrors,
...currencyErrors,
@@ -45,8 +46,8 @@ export const formatCheckLib = (payload, instanceId, api_secret, useFirebase) =>
]
}
-const isValidAppOrClientId = (payload, useFirebase) => {
- let errors: ValidationMessage[] = []
+const isValidAppOrClientId = (payload: any, useFirebase: boolean) => {
+ const errors: ValidationMessage[] = []
const appInstanceId = payload.app_instance_id
const clientId = payload.client_id
@@ -92,10 +93,10 @@ const isValidAppOrClientId = (payload, useFirebase) => {
}
-const isValidEventName = (payload) => {
+const isValidEventName = (payload: any) => {
let errors: ValidationMessage[] = []
- payload.events?.forEach(ev => {
+ payload.events?.forEach((ev: any) => {
if (RESERVED_EVENT_NAMES.includes(ev.name)) {
errors.push({
description: `${ev.name} is a reserved event name`,
@@ -108,8 +109,8 @@ const isValidEventName = (payload) => {
return errors
}
-const isValidUserPropertyName = (payload) => {
- let errors: ValidationMessage[] = []
+const isValidUserPropertyName = (payload: any) => {
+ const errors: ValidationMessage[] = []
const userProperties = payload.user_properties
if (userProperties) {
@@ -127,10 +128,10 @@ const isValidUserPropertyName = (payload) => {
return errors
}
-const isValidCurrencyType = (payload) => {
- let errors: ValidationMessage[] = []
+const isValidCurrencyType = (payload: any) => {
+ const errors: ValidationMessage[] = []
- payload.events?.forEach(ev => {
+ payload.events?.forEach((ev:any) => {
if (ev.params && ev.params.currency) {
const currency = ev.params.currency
@@ -147,10 +148,10 @@ const isValidCurrencyType = (payload) => {
return errors
}
-const isItemsEmpty = (payload) => {
- let errors: ValidationMessage[] = []
+const isItemsEmpty = (payload: any) => {
+ const errors: ValidationMessage[] = []
- payload?.events?.forEach(ev => {
+ payload?.events?.forEach((ev: any) => {
if (ev?.params?.items && ev?.params?.items?.length < 1 && eventRequiresItems(ev?.params?.name)){
errors.push({
description: "'items' should not be empty; One of 'item_id' or 'item_name' is a required key",
@@ -163,18 +164,20 @@ const isItemsEmpty = (payload) => {
return errors
}
-const eventRequiresItems = (eventName) => {
+const eventRequiresItems = (eventName: string) => {
+ // @ts-ignore
if (eventDefinitions[eventName]) {
+ // @ts-ignore
return eventDefinitions[eventName].includes('items')
}
return false
}
-const itemsHaveRequiredKey = (payload) => {
- let errors: ValidationMessage[] = []
+const itemsHaveRequiredKey = (payload: any) => {
+ const errors: ValidationMessage[] = []
- payload?.events?.forEach(ev => {
+ payload?.events?.forEach((ev: any) => {
if (ev?.params?.items?.length > 0) {
const itemsObj = ev.params.items[0]
@@ -191,16 +194,16 @@ const itemsHaveRequiredKey = (payload) => {
return errors
}
-const requiredKeysDontExist = (itemsObj) => {
+const requiredKeysDontExist = (itemsObj: any) => {
return !(itemsObj.hasOwnProperty('item_id') || itemsObj.hasOwnProperty('item_name'))
}
-const requiredKeysEmpty = (itemsObj) => {
+const requiredKeysEmpty = (itemsObj: any) => {
return !(itemsObj.item_id || itemsObj.item_name)
}
-const isInstanceIdValid = (instanceId, useFirebase) => {
- let errors: ValidationMessage[] = []
+const isInstanceIdValid = (instanceId: InstanceId, useFirebase: boolean) => {
+ const errors: ValidationMessage[] = []
const firebaseAppId = instanceId?.firebase_app_id
const measurementId = instanceId?.measurement_id
@@ -225,8 +228,8 @@ const isInstanceIdValid = (instanceId, useFirebase) => {
return errors
}
-const isApiSecretNotNull = (api_secret) => {
- let errors: ValidationMessage[] = []
+const isApiSecretNotNull = (api_secret: string) => {
+ const errors: ValidationMessage[] = []
if (!api_secret) {
errors.push({
@@ -239,8 +242,8 @@ const isApiSecretNotNull = (api_secret) => {
return errors
}
-const isTooBig = (payload) => {
- let errors: ValidationMessage[] = []
+const isTooBig = (payload: any) => {
+ const errors: ValidationMessage[] = []
if (sizeof(payload) > 130000) {
errors.push({
diff --git a/src/components/ga4/EventBuilder/ValidateEvent/handlers/responseUtil.ts b/src/components/ga4/EventBuilder/ValidateEvent/handlers/responseUtil.ts
index 4e5d713e4..4c387b07d 100644
--- a/src/components/ga4/EventBuilder/ValidateEvent/handlers/responseUtil.ts
+++ b/src/components/ga4/EventBuilder/ValidateEvent/handlers/responseUtil.ts
@@ -1,3 +1,5 @@
+import { ValidationMessage } from "../../types"
+
const ALPHA_NUMERIC_NAME = "does not match '^(?!ga_|google_|firebase_)[A-Za-z][A-Za-z0-9_]*$'"
const ALPHA_NUMERIC_OVERRIDE = " may only contain alpha-numeric characters and underscores,start with an alphabetic character, and cannot contain google_, ga_, firebase_"
const CUSTOM_PARAMS_NAME = "can have at most [10] custom params."
@@ -14,7 +16,7 @@ const API_DOC_GTAG = 'https://developers.google.com/analytics/devguides/collecti
const BASE_PAYLOAD_ATTRIBUTES = ['app_instance_id', 'api_secret', 'firebase_app_id', 'user_id', 'timestamp_micros', 'user_properties', 'non_personalized_ads']
// formats error messages for clarity; add documentation to each error
-export const formatErrorMessages = (errors, payload, useFirebase) => {
+export const formatErrorMessages = (errors: ValidationMessage[], payload: any, useFirebase: boolean) => {
const formattedErrors = errors.map(error => {
const { description, fieldPath } = error
@@ -29,15 +31,11 @@ export const formatErrorMessages = (errors, payload, useFirebase) => {
error['description'] = description.slice(0, end_index) + ALPHA_NUMERIC_OVERRIDE
return error
-
} else if (BASE_PAYLOAD_ATTRIBUTES.includes(fieldPath?.slice(2))) {
error['fieldPath'] = fieldPath.slice(2)
-
return error
}
-
return error
-
})
const documentedErrors = formattedErrors.map(error => {
@@ -48,7 +46,7 @@ export const formatErrorMessages = (errors, payload, useFirebase) => {
return documentedErrors
}
-const addDocumentation = (error, payload, useFirebase) => {
+const addDocumentation = (error: ValidationMessage, payload: any, useFirebase: boolean) => {
const { fieldPath, validationCode } = error
if (validationCode === 'max-length-error' || validationCode === 'max-properties-error' || validationCode === 'max-body-size') {
diff --git a/src/components/ga4/EventBuilder/ValidateEvent/index.tsx b/src/components/ga4/EventBuilder/ValidateEvent/index.tsx
index 80624ab73..43fa96e48 100644
--- a/src/components/ga4/EventBuilder/ValidateEvent/index.tsx
+++ b/src/components/ga4/EventBuilder/ValidateEvent/index.tsx
@@ -14,27 +14,24 @@
import React, { useContext } from "react"
-import { makeStyles } from "@material-ui/core/styles"
+import { styled } from '@mui/material/styles';
+
import clsx from "classnames"
-import useFormStyles from "@/hooks/useFormStyles"
import useValidateEvent from "./useValidateEvent"
import Loadable from "@/components/Loadable"
-import Typography from "@material-ui/core/Typography"
+import Typography from "@mui/material/Typography"
import { PAB, PlainButton } from "@/components/Buttons"
-import { Check, Warning, Error as ErrorIcon } from "@material-ui/icons"
+import { Check, Warning, Error as ErrorIcon } from "@mui/icons-material"
import PrettyJson from "@/components/PrettyJson"
import usePayload from "./usePayload"
import { ValidationMessage } from "../types"
import Spinner from "@/components/Spinner"
import { EventCtx, Label } from ".."
-import { Card } from "@material-ui/core"
-import { green, red } from "@material-ui/core/colors"
+import { Card } from "@mui/material"
+import { green, red } from "@mui/material/colors"
-interface StyleProps {
- error?: boolean
- valid?: boolean
-}
+const PREFIX = 'ValidateEvent';
interface TemplateProps {
heading: string
@@ -64,18 +61,35 @@ export interface ValidateEventProps {
useTextBox: boolean
}
-const useStyles = makeStyles(theme => ({
- template: {
+const classes = {
+ template: `${PREFIX}-template`,
+ payloadTitle: `${PREFIX}-payloadTitle`,
+ headers: `${PREFIX}-headers`,
+ heading: `${PREFIX}-heading`,
+ payload: `${PREFIX}-payload`,
+ form: `${PREFIX}-form`,
+ buttonRow: `${PREFIX}-buttonRow`
+};
+
+const Root = styled('div')((
+ {
+ theme
+ }
+) => ({
+ [`& .${classes.template}`]: {
padding: theme.spacing(2),
},
- payloadTitle: {
+
+ [`& .${classes.payloadTitle}`]: {
margin: theme.spacing(1, 0),
},
- headers: {
+
+ [`& .${classes.headers}`]: {
...theme.typography.body2,
fontFamily: "monospace",
},
- heading: ({ error, valid }: StyleProps) => ({
+
+ [`& .${classes.heading}`]: ({ error, valid }: StyleProps) => ({
backgroundColor: error ? red[300] : valid ? green[300] : "inherit",
color: error
? theme.palette.getContrastText(red[300])
@@ -91,16 +105,33 @@ const useStyles = makeStyles(theme => ({
},
marginBottom: theme.spacing(2),
}),
- payload: {
- fontSize: theme.typography.caption.fontSize,
+
+ [`& .${classes.form}`]: {
+ maxWidth: "80ch",
+ },
+
+ [`& .${classes.buttonRow}`]: {
+ display: "flex",
+ "&> *:not(:last-child)": {
+ marginRight: theme.spacing(1),
+ },
},
-}))
+ [`& .${classes.payload}`]: {
+ fontSize: theme.typography.caption.fontSize,
+ }
+}));
-const focusFor = (message: ValidationMessage, useTextBox) => {
+interface StyleProps {
+ error?: boolean
+ valid?: boolean
+}
+
+
+const focusFor = (message: ValidationMessage, useTextBox: boolean) => {
const { fieldPath } = message
let id: string | undefined
- let labelValues: string[] = Object.values(Label)
+ const labelValues: string[] = Object.values(Label)
if (labelValues.includes(fieldPath) && !useTextBox) {
id = fieldPath
@@ -137,14 +168,12 @@ const Template: React.FC = ({
payloadErrors,
useTextBox
}) => {
+
const { instanceId, api_secret } = useContext(EventCtx)!
- const classes = useStyles({ error, valid })
const payload = usePayload()
- const formClasses = useFormStyles()
-
return (
@@ -152,19 +181,19 @@ const Template: React.FC = ({
{heading}
- {validationMessages !== undefined &&
+ {validationMessages !== undefined &&
(
(useTextBox && !payloadErrors) ||
- !useTextBox
+ !useTextBox
) && (