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 = {