diff --git a/apps/web/components/imports/editor/Editor.tsx b/apps/web/components/imports/editor/Editor.tsx index b32faaf8f..9ede8cb4b 100644 --- a/apps/web/components/imports/editor/Editor.tsx +++ b/apps/web/components/imports/editor/Editor.tsx @@ -49,6 +49,9 @@ export function OutputEditor({ templateId, switchToDestination }: OutputEditorPr isSyncCustomizationLoading, isCustomizationLoading, isDestinationLoading, + allVariables, + formatVariableDisplay, + isSystemVariable, } = useEditor({ templateId, }); @@ -98,7 +101,7 @@ export function OutputEditor({ templateId, switchToDestination }: OutputEditorPr id="format" value={field.value} onChange={field.onChange} - variables={[...(customization?.recordVariables || []), ...(customization?.chunkVariables || [])]} + variables={allVariables} /> )} /> @@ -107,14 +110,16 @@ export function OutputEditor({ templateId, switchToDestination }: OutputEditorPr
- {customization?.chunkVariables.map((variable) => ( - + {allVariables.filter(isSystemVariable).map((variable) => ( + ))} - {customization?.recordVariables.map((variable) => ( - - ))} + {allVariables + .filter((variable) => !isSystemVariable(variable)) + .map((variable) => ( + + ))}
diff --git a/apps/web/components/imports/validator/Validator.tsx b/apps/web/components/imports/validator/Validator.tsx index 60c95816d..94688538f 100644 --- a/apps/web/components/imports/validator/Validator.tsx +++ b/apps/web/components/imports/validator/Validator.tsx @@ -20,13 +20,19 @@ import { useValidator } from '@hooks/useValidator'; import { VarItemWrapper } from '../editor/VarItemWrapper'; import { InformationIcon } from '@assets/icons/Information.icon'; import { TooltipLink } from '@components/guide-point'; +import { useMemo } from 'react'; +import { useEditor } from '@hooks/useEditor'; +import { DestinationsEnum } from '@impler/shared'; interface ValidatorProps { templateId: string; } export function Validator({ templateId }: ValidatorProps) { - const systemVariables = [ + const { destination } = useEditor({ templateId }); + + // Existing system variables + const baseSystemVariables = [ 'params.uploadId', 'params.fileName', 'params.data', @@ -34,12 +40,26 @@ export function Validator({ templateId }: ValidatorProps) { 'params.totalRecords', 'params.chunkSize', ]; + + // Bubble.io specific system variables + const bubbleIoSystemVariables = ['extra.uploadId', 'extra.userId']; + const { colorScheme } = useMantineColorScheme(); const { control, editorVariables, onSave, isUpdateValidationsLoading, isValidationsLoading, testCodeResult } = useValidator({ templateId, }); + // Combine all variables: base system variables + editor variables + Bubble.io variables (if applicable) + const allVariables = useMemo(() => { + const variables = [...baseSystemVariables, ...editorVariables]; + if (destination?.destination === DestinationsEnum.BUBBLEIO) { + variables.push(...bubbleIoSystemVariables); + } + + return variables; + }, [destination?.destination, editorVariables]); + return (
@@ -124,7 +144,7 @@ export function Validator({ templateId }: ValidatorProps) { mode="javascript" value={field.value} onChange={field.onChange} - variables={[...systemVariables]} + variables={allVariables} /> )} /> @@ -134,15 +154,10 @@ export function Validator({ templateId }: ValidatorProps) {
- {systemVariables.map((variable) => ( + {allVariables.map((variable) => ( ))} - - {editorVariables.map((variable) => ( - - ))} -
diff --git a/apps/web/hooks/useEditor.tsx b/apps/web/hooks/useEditor.tsx index 078148118..6402bb475 100644 --- a/apps/web/hooks/useEditor.tsx +++ b/apps/web/hooks/useEditor.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useEffect, useMemo } from 'react'; import { useForm } from 'react-hook-form'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; @@ -83,6 +83,38 @@ export function useEditor({ templateId }: UseEditorProps) { } ); + // Combine all variables: record variables + chunk variables + system variables + const allVariables = useMemo(() => { + const variables = []; + + // Add schema variables (from record format) + if (customization?.recordVariables) { + variables.push(...customization.recordVariables.map((variable) => variable.substring(2, variable.length - 2))); + } + + // Add system variables (from chunk format) + if (customization?.chunkVariables) { + variables.push(...customization.chunkVariables); + } + + // Add Bubble.io specific system variables + if (destination?.destination === DestinationsEnum.BUBBLEIO) { + variables.push('extra.uploadId', 'extra.userId'); + } + + return variables; + }, [customization?.recordVariables, customization?.chunkVariables, destination?.destination]); + + // Helper function to format variable display + const formatVariableDisplay = (variable: string) => { + return `"${variable}"`; + }; + + // Helper function to categorize variables + const isSystemVariable = (variable: string) => { + return variable.startsWith('extra.') || variable.startsWith('params.'); + }; + const validateFormat = (data: string): boolean => { try { JSON.parse(data); @@ -137,10 +169,13 @@ export function useEditor({ templateId }: UseEditorProps) { onSaveClick, destination, handleSubmit, + allVariables, customization, + isSystemVariable, syncCustomization, updateCustomization, isDestinationLoading, + formatVariableDisplay, isCustomizationLoading, isSyncCustomizationLoading, isUpdateCustomizationLoading, diff --git a/apps/web/hooks/useValidator.tsx b/apps/web/hooks/useValidator.tsx index 4a46cacf9..18ccb05fc 100644 --- a/apps/web/hooks/useValidator.tsx +++ b/apps/web/hooks/useValidator.tsx @@ -7,7 +7,7 @@ import { notify } from '@libs/notify'; import { commonApi } from '@libs/api'; import { track } from '@libs/amplitude'; import { API_KEYS, MODAL_KEYS, MODAL_TITLES } from '@config'; -import { ICustomization, IErrorObject, IValidator } from '@impler/shared'; +import { ICustomization, IErrorObject, IValidator, DestinationsEnum } from '@impler/shared'; import { CodeOutput } from '@components/imports/validator/CodeOutput'; interface UseSchemaProps { @@ -43,9 +43,14 @@ export function useValidator({ templateId }: UseSchemaProps) { () => commonApi(API_KEYS.TEMPLATE_CUSTOMIZATION_GET as any, { parameters: [templateId] }), { onSuccess(data) { - setEditorVariables([ - ...(data.recordVariables.map((variable) => variable.substring(2, variable.length - 2)) || []), - ]); + // Get base variables from customization + const baseVariables = data.recordVariables?.map((variable) => variable.substring(2, variable.length - 2)) || []; + + // Add static Bubble.io variables if destination is Bubble.io + const bubbleIoVariables = + data.destination === DestinationsEnum.BUBBLEIO ? ['extra.uploadId', 'extra.userId'] : []; + + setEditorVariables([...baseVariables, ...bubbleIoVariables]); }, } ); diff --git a/libs/shared/src/entities/Customization/Customization.interface.ts b/libs/shared/src/entities/Customization/Customization.interface.ts index 198b8b13b..c0735fb4b 100644 --- a/libs/shared/src/entities/Customization/Customization.interface.ts +++ b/libs/shared/src/entities/Customization/Customization.interface.ts @@ -1,6 +1,9 @@ +import { DestinationsEnum } from '../../types/destination/destination.types'; + export interface ICustomization { _id: string; _templateId: string; + destination: DestinationsEnum; recordVariables: string[]; chunkVariables: string[]; recordFormat: string; diff --git a/libs/shared/src/utils/output.helpers.ts b/libs/shared/src/utils/output.helpers.ts index 170a68000..024e040b0 100644 --- a/libs/shared/src/utils/output.helpers.ts +++ b/libs/shared/src/utils/output.helpers.ts @@ -148,3 +148,17 @@ export function getRecordFormat(chunkFormat: string) { chunkFormat: JSON.stringify(format), }; } + +export function extractExtraSystemVariables(format: string): string[] { + const variablePattern = /\{\{([^}]+)\}\}/g; + const variables: string[] = []; + let match; + + while ((match = variablePattern.exec(format)) !== null) { + variables.push(match[1]); + } + + const systemVariables = variables.filter((variable) => variable.startsWith('extra.')); + + return systemVariables; +}