Add fields to update in update record action (#9108)

- update backend action so it handles composite fields
- add fields to update multiselect
- generate form based on that field
- add icons
This commit is contained in:
Thomas Trompette
2024-12-18 14:32:21 +01:00
committed by GitHub
parent b6508cc615
commit 94676215ad
9 changed files with 191 additions and 15 deletions

View File

@ -44,6 +44,7 @@ export type WorkflowUpdateRecordActionSettings = BaseWorkflowActionSettings & {
objectName: string;
objectRecord: ObjectRecord;
objectRecordId: string;
fieldsToUpdate: string[];
};
};

View File

@ -12,9 +12,14 @@ import {
useIcons,
} from 'twenty-ui';
import { formatFieldMetadataItemAsFieldDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsFieldDefinition';
import { FormFieldInput } from '@/object-record/record-field/components/FormFieldInput';
import { FormMultiSelectFieldInput } from '@/object-record/record-field/form-types/components/FormMultiSelectFieldInput';
import { WorkflowStepBody } from '@/workflow/components/WorkflowStepBody';
import { WorkflowVariablePicker } from '@/workflow/components/WorkflowVariablePicker';
import { JsonValue } from 'type-fest';
import { useDebouncedCallback } from 'use-debounce';
import { FieldMetadataType } from '~/generated-metadata/graphql';
type WorkflowEditActionFormUpdateRecordProps = {
action: WorkflowUpdateRecordAction;
@ -31,9 +36,23 @@ type WorkflowEditActionFormUpdateRecordProps = {
type UpdateRecordFormData = {
objectName: string;
objectRecordId: string;
fieldsToUpdate: string[];
[field: string]: unknown;
};
const AVAILABLE_FIELD_METADATA_TYPES = [
FieldMetadataType.Text,
FieldMetadataType.Number,
FieldMetadataType.Date,
FieldMetadataType.Boolean,
FieldMetadataType.Select,
FieldMetadataType.MultiSelect,
FieldMetadataType.Emails,
FieldMetadataType.Links,
FieldMetadataType.FullName,
FieldMetadataType.Address,
];
export const WorkflowEditActionFormUpdateRecord = ({
action,
actionOptions,
@ -53,6 +72,7 @@ export const WorkflowEditActionFormUpdateRecord = ({
const [formData, setFormData] = useState<UpdateRecordFormData>({
objectName: action.settings.input.objectName,
objectRecordId: action.settings.input.objectRecordId,
fieldsToUpdate: action.settings.input.fieldsToUpdate ?? [],
...action.settings.input.objectRecord,
});
const isFormDisabled = actionOptions.readonly;
@ -75,6 +95,7 @@ export const WorkflowEditActionFormUpdateRecord = ({
setFormData({
objectName: action.settings.input.objectName,
objectRecordId: action.settings.input.objectRecordId,
fieldsToUpdate: action.settings.input.fieldsToUpdate ?? [],
...action.settings.input.objectRecord,
});
}, [action.settings.input]);
@ -88,6 +109,27 @@ export const WorkflowEditActionFormUpdateRecord = ({
throw new Error('Should have found the metadata item');
}
const inlineFieldMetadataItems = selectedObjectMetadataItem.fields
.filter(
(fieldMetadataItem) =>
!fieldMetadataItem.isSystem &&
fieldMetadataItem.isActive &&
AVAILABLE_FIELD_METADATA_TYPES.includes(fieldMetadataItem.type),
)
.sort((fieldMetadataItemA, fieldMetadataItemB) =>
fieldMetadataItemA.name.localeCompare(fieldMetadataItemB.name),
);
const inlineFieldDefinitions = inlineFieldMetadataItems.map(
(fieldMetadataItem) =>
formatFieldMetadataItemAsFieldDefinition({
field: fieldMetadataItem,
objectMetadataItem: selectedObjectMetadataItem,
showLabel: true,
labelWidth: 90,
}),
);
const saveAction = useDebouncedCallback(
async (formData: UpdateRecordFormData) => {
if (actionOptions.readonly === true) {
@ -97,6 +139,7 @@ export const WorkflowEditActionFormUpdateRecord = ({
const {
objectName: updatedObjectName,
objectRecordId: updatedObjectRecordId,
fieldsToUpdate: updatedFieldsToUpdate,
...updatedOtherFields
} = formData;
@ -108,6 +151,7 @@ export const WorkflowEditActionFormUpdateRecord = ({
objectName: updatedObjectName,
objectRecordId: updatedObjectRecordId ?? '',
objectRecord: updatedOtherFields,
fieldsToUpdate: updatedFieldsToUpdate ?? [],
},
},
});
@ -154,6 +198,7 @@ export const WorkflowEditActionFormUpdateRecord = ({
const newFormData: UpdateRecordFormData = {
objectName: updatedObjectName,
objectRecordId: '',
fieldsToUpdate: [],
};
setFormData(newFormData);
@ -172,6 +217,48 @@ export const WorkflowEditActionFormUpdateRecord = ({
objectNameSingular={formData.objectName}
defaultValue={formData.objectRecordId}
/>
<FormMultiSelectFieldInput
label="Fields to update"
defaultValue={formData.fieldsToUpdate}
options={inlineFieldDefinitions.map((field) => ({
label: field.label,
value: field.metadata.fieldName,
icon: getIcon(field.iconName),
color: 'gray',
}))}
onPersist={(fieldsToUpdate) =>
handleFieldChange('fieldsToUpdate', fieldsToUpdate)
}
/>
<HorizontalSeparator noMargin />
{formData.fieldsToUpdate.map((fieldName) => {
const fieldDefinition = inlineFieldDefinitions.find(
(definition) => definition.metadata.fieldName === fieldName,
);
if (!isDefined(fieldDefinition)) {
return null;
}
const currentValue = formData[
fieldDefinition.metadata.fieldName
] as JsonValue;
return (
<FormFieldInput
key={fieldDefinition.metadata.fieldName}
defaultValue={currentValue}
field={fieldDefinition}
onPersist={(value) => {
handleFieldChange(fieldDefinition.metadata.fieldName, value);
}}
VariablePicker={WorkflowVariablePicker}
/>
);
})}
</WorkflowStepBody>
</>
);