diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCodeFields.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCodeFields.tsx index deb44af178..ed90400e8c 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCodeFields.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCodeFields.tsx @@ -10,7 +10,7 @@ import { getWorkflowCodeFieldsEnumSelectOptions } from '@/workflow/workflow-step import { getWorkflowCodeFieldsLeafKind } from '@/workflow/workflow-steps/workflow-actions/code-action/utils/getWorkflowCodeFieldsLeafKind'; import { styled } from '@linaria/react'; import { t } from '@lingui/core/macro'; -import { isNonEmptyArray, isObject } from '@sniptt/guards'; +import { isNonEmptyArray, isNonEmptyString, isObject } from '@sniptt/guards'; import { isDefined } from 'twenty-shared/utils'; import { type FunctionInput, type InputSchema } from 'twenty-shared/workflow'; import { themeCssVariables } from 'twenty-ui/theme-constants'; @@ -51,10 +51,18 @@ export const WorkflowEditActionCodeFields = ({ const currentPath = [...path, inputKey]; const pathKey = currentPath.join('.'); + const schemaProperty = getInputSchemaPropertyAtPath( + inputSchema, + currentPath, + ); + const displayLabel = isNonEmptyString(schemaProperty?.label) + ? schemaProperty.label + : inputKey; + if (inputValue !== null && isObject(inputValue)) { return (
- {inputKey} + {displayLabel} { expect(result[0].properties?.title).toEqual({ type: 'string' }); expect(result[0].properties?.other).toEqual({ type: 'string' }); }); + + it('preserves label on top-level and nested properties', () => { + const result = jsonSchemaToInputSchema({ + type: 'object', + label: 'Slack Message', + properties: { + slackChannelId: { type: 'string', label: 'Channel' }, + messageText: { type: 'string', label: 'Message text' }, + meta: { + type: 'object', + properties: { + count: { type: 'integer', label: 'Count' }, + }, + }, + }, + }); + + expect(result[0].label).toBe('Slack Message'); + expect(result[0].properties?.slackChannelId).toEqual({ + type: 'string', + label: 'Channel', + }); + expect(result[0].properties?.messageText).toEqual({ + type: 'string', + label: 'Message text', + }); + expect(result[0].properties?.meta?.properties?.count).toEqual({ + type: 'number', + label: 'Count', + }); + }); + + it('does not set label when empty or omitted', () => { + const result = jsonSchemaToInputSchema({ + type: 'object', + properties: { + empty: { type: 'string', label: '' }, + missing: { type: 'string' }, + }, + }); + + expect(result[0].properties?.empty).toEqual({ type: 'string' }); + expect(result[0].properties?.missing).toEqual({ type: 'string' }); + }); }); diff --git a/packages/twenty-shared/src/logic-function/input-json-schema.type.ts b/packages/twenty-shared/src/logic-function/input-json-schema.type.ts index ec0f817986..782764eede 100644 --- a/packages/twenty-shared/src/logic-function/input-json-schema.type.ts +++ b/packages/twenty-shared/src/logic-function/input-json-schema.type.ts @@ -16,4 +16,5 @@ export type InputJsonSchema = { minimum?: number; maximum?: number; multiline?: boolean; + label?: string; }; diff --git a/packages/twenty-shared/src/logic-function/json-schema-to-input-schema.ts b/packages/twenty-shared/src/logic-function/json-schema-to-input-schema.ts index dd2bb5cda1..2c0a17633a 100644 --- a/packages/twenty-shared/src/logic-function/json-schema-to-input-schema.ts +++ b/packages/twenty-shared/src/logic-function/json-schema-to-input-schema.ts @@ -3,6 +3,7 @@ import { type InputSchema, type InputSchemaProperty, } from '@/workflow/types/InputSchema'; +import { isNonEmptyString } from '@sniptt/guards'; const convertProperty = (jsonSchema: InputJsonSchema): InputSchemaProperty => { const property: InputSchemaProperty = { type: 'unknown' }; @@ -50,6 +51,10 @@ const convertProperty = (jsonSchema: InputJsonSchema): InputSchemaProperty => { property.multiline = true; } + if (isNonEmptyString(jsonSchema.label)) { + property.label = jsonSchema.label; + } + return property; }; diff --git a/packages/twenty-shared/src/workflow/types/InputSchema.ts b/packages/twenty-shared/src/workflow/types/InputSchema.ts index 83cffd9a5c..1032899323 100644 --- a/packages/twenty-shared/src/workflow/types/InputSchema.ts +++ b/packages/twenty-shared/src/workflow/types/InputSchema.ts @@ -9,6 +9,7 @@ export type InputSchemaProperty = { items?: InputSchemaProperty; properties?: Properties; multiline?: boolean; + label?: string; }; type Properties = {