Form action fast follows (#11242)

- on form action, add trash on hover and fix spacing
- fix dark mode
- second batch of icon fixes

<img width="692" alt="Capture d’écran 2025-03-27 à 18 25 48"
src="https://github.com/user-attachments/assets/963f50d2-12ee-425c-97a3-2ad0c6bb5c57"
/>
This commit is contained in:
Thomas Trompette
2025-03-28 10:11:01 +01:00
committed by GitHub
parent 78943b3370
commit 8d35454dd8
8 changed files with 116 additions and 75 deletions

View File

@ -39,7 +39,6 @@ import {
IconFileImport,
IconHeart,
IconHeartOff,
IconHistory,
IconHistoryToggle,
IconNoteOff,
IconPlayerPause,
@ -49,6 +48,7 @@ import {
IconRotate2,
IconTrash,
IconTrashX,
IconVersions,
} from 'twenty-ui';
export const WORKFLOW_ACTIONS_CONFIG: Record<
@ -120,7 +120,7 @@ export const WORKFLOW_ACTIONS_CONFIG: Record<
shortLabel: msg`See active version`,
isPinned: false,
position: 4,
Icon: IconHistory,
Icon: IconVersions,
type: ActionMenuEntryType.Standard,
scope: ActionMenuEntryScope.RecordSelection,
availableOn: [
@ -150,7 +150,7 @@ export const WORKFLOW_ACTIONS_CONFIG: Record<
shortLabel: msg`See versions`,
isPinned: false,
position: 6,
Icon: IconHistory,
Icon: IconVersions,
type: ActionMenuEntryType.Standard,
scope: ActionMenuEntryScope.RecordSelection,
availableOn: [

View File

@ -27,9 +27,9 @@ import {
IconEyeOff,
IconHeart,
IconHeartOff,
IconHistory,
IconRotate2,
IconSettingsAutomation,
IconVersions,
} from 'twenty-ui';
export const WORKFLOW_RUNS_ACTIONS_CONFIG: Record<
@ -61,7 +61,7 @@ export const WORKFLOW_RUNS_ACTIONS_CONFIG: Record<
isPinned: true,
type: ActionMenuEntryType.Standard,
scope: ActionMenuEntryScope.RecordSelection,
Icon: IconHistory,
Icon: IconVersions,
availableOn: [
ActionViewType.SHOW_PAGE,
ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,

View File

@ -30,11 +30,11 @@ import {
IconEyeOff,
IconHeart,
IconHeartOff,
IconHistory,
IconHistoryToggle,
IconPencil,
IconRotate2,
IconSettingsAutomation,
IconVersions,
} from 'twenty-ui';
export const WORKFLOW_VERSIONS_ACTIONS_CONFIG: Record<
@ -95,7 +95,7 @@ export const WORKFLOW_VERSIONS_ACTIONS_CONFIG: Record<
position: 4,
type: ActionMenuEntryType.Standard,
scope: ActionMenuEntryScope.RecordSelection,
Icon: IconHistory,
Icon: IconVersions,
availableOn: [
ActionViewType.SHOW_PAGE,
ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,

View File

@ -81,13 +81,18 @@ const StyledIconButtonContainer = styled.div`
}
`;
const StyledAddFieldContainer = styled.div`
display: flex;
const StyledAddFieldButtonContainer = styled.div`
padding-top: ${({ theme }) => theme.spacing(2)};
`;
const StyledAddFieldButtonContentContainer = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.secondary};
display: flex;
font-weight: ${({ theme }) => theme.font.weight.medium};
gap: ${({ theme }) => theme.spacing(0.5)};
justify-content: center;
width: 100%;
gap: ${({ theme }) => theme.spacing(0.5)};
`;
export const WorkflowEditActionFormBuilder = ({
@ -106,7 +111,9 @@ export const WorkflowEditActionFormBuilder = ({
const headerType = useActionHeaderTypeOrThrow(action.type);
const [selectedField, setSelectedField] = useState<string | null>(null);
const [hoveredField, setHoveredField] = useState<string | null>(null);
const isFieldSelected = (fieldName: string) => selectedField === fieldName;
const isFieldHovered = (fieldName: string) => hoveredField === fieldName;
const handleFieldClick = (fieldName: string) => {
if (actionOptions.readonly === true) {
return;
@ -177,7 +184,10 @@ export const WorkflowEditActionFormBuilder = ({
<FormFieldInputContainer key={field.id}>
{field.label ? <InputLabel>{field.label}</InputLabel> : null}
<StyledRowContainer>
<StyledRowContainer
onMouseEnter={() => setHoveredField(field.id)}
onMouseLeave={() => setHoveredField(null)}
>
<FormFieldInputRowContainer>
<FormFieldInputInputContainer
hasRightElement={false}
@ -201,29 +211,30 @@ export const WorkflowEditActionFormBuilder = ({
</StyledFieldContainer>
</FormFieldInputInputContainer>
</FormFieldInputRowContainer>
{!actionOptions.readonly && isFieldSelected(field.id) && (
<StyledIconButtonContainer>
<IconTrash
size={theme.icon.size.md}
color={theme.font.color.secondary}
onClick={() => {
const updatedFormData = formData.filter(
(currentField) => currentField.id !== field.id,
);
{!actionOptions.readonly &&
(isFieldSelected(field.id) || isFieldHovered(field.id)) && (
<StyledIconButtonContainer>
<IconTrash
size={theme.icon.size.md}
color={theme.font.color.secondary}
onClick={() => {
const updatedFormData = formData.filter(
(currentField) => currentField.id !== field.id,
);
setFormData(updatedFormData);
setFormData(updatedFormData);
actionOptions.onActionUpdate({
...action,
settings: {
...action.settings,
input: updatedFormData,
},
});
}}
/>
</StyledIconButtonContainer>
)}
actionOptions.onActionUpdate({
...action,
settings: {
...action.settings,
input: updatedFormData,
},
});
}}
/>
</StyledIconButtonContainer>
)}
{isFieldSelected(field.id) && (
<WorkflowEditActionFormFieldSettings
field={field}
@ -237,44 +248,46 @@ export const WorkflowEditActionFormBuilder = ({
</FormFieldInputContainer>
))}
{!actionOptions.readonly && (
<StyledRowContainer>
<FormFieldInputContainer>
<FormFieldInputRowContainer>
<FormFieldInputInputContainer
hasRightElement={false}
onClick={() => {
const { label, placeholder, name } =
getDefaultFormFieldSettings(FieldMetadataType.TEXT);
<StyledAddFieldButtonContainer>
<StyledRowContainer>
<FormFieldInputContainer>
<FormFieldInputRowContainer>
<FormFieldInputInputContainer
hasRightElement={false}
onClick={() => {
const { label, placeholder, name } =
getDefaultFormFieldSettings(FieldMetadataType.TEXT);
const newField: WorkflowFormActionField = {
id: v4(),
name,
type: FieldMetadataType.TEXT,
label,
placeholder,
};
const newField: WorkflowFormActionField = {
id: v4(),
name,
type: FieldMetadataType.TEXT,
label,
placeholder,
};
setFormData([...formData, newField]);
setFormData([...formData, newField]);
actionOptions.onActionUpdate({
...action,
settings: {
...action.settings,
input: [...action.settings.input, newField],
},
});
}}
>
<StyledFieldContainer>
<StyledAddFieldContainer>
<IconPlus size={theme.icon.size.sm} />
{t`Add Field`}
</StyledAddFieldContainer>
</StyledFieldContainer>
</FormFieldInputInputContainer>
</FormFieldInputRowContainer>
</FormFieldInputContainer>
</StyledRowContainer>
actionOptions.onActionUpdate({
...action,
settings: {
...action.settings,
input: [...action.settings.input, newField],
},
});
}}
>
<StyledFieldContainer>
<StyledAddFieldButtonContentContainer>
<IconPlus size={theme.icon.size.sm} />
{t`Add Field`}
</StyledAddFieldButtonContentContainer>
</StyledFieldContainer>
</FormFieldInputInputContainer>
</FormFieldInputRowContainer>
</FormFieldInputContainer>
</StyledRowContainer>
</StyledAddFieldButtonContainer>
)}
</WorkflowStepBody>
</>

View File

@ -44,12 +44,14 @@ const StyledSettingsHeader = styled.div`
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
display: grid;
gap: ${({ theme }) => theme.spacing(1)};
padding-inline: ${({ theme }) => theme.spacing(3)};
padding-right: ${({ theme }) => theme.spacing(2)};
padding-left: ${({ theme }) => theme.spacing(3)};
grid-template-columns: 1fr 24px;
padding-bottom: ${({ theme }) => theme.spacing(3)};
`;
const StyledTitleContainer = styled.div`
color: ${({ theme }) => theme.font.color.primary};
display: flex;
flex-direction: row;
gap: ${({ theme }) => theme.spacing(1)};

View File

@ -14,7 +14,7 @@ export const workflowRunsAllView = (
type: 'table',
key: 'INDEX',
position: 0,
icon: 'IconHistory',
icon: 'IconHistoryToggle',
openRecordIn: ViewOpenRecordInType.RECORD_PAGE,
kanbanFieldMetadataId: '',
filters: [],

View File

@ -8,6 +8,7 @@ import {
WorkflowRunStatus,
WorkflowRunWorkspaceEntity,
} from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
import { WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
import {
@ -39,12 +40,36 @@ export class WorkflowRunWorkspaceService {
workflowVersionId,
);
const workflowRepository =
await this.twentyORMManager.getRepository<WorkflowWorkspaceEntity>(
'workflow',
);
const workflow = await workflowRepository.findOne({
where: {
id: workflowVersion.workflowId,
},
});
if (!workflow) {
throw new WorkflowRunException(
'Workflow id is invalid',
WorkflowRunExceptionCode.WORKFLOW_RUN_INVALID,
);
}
const workflowRunCount = await workflowRunRepository.count({
where: {
workflowId: workflow.id,
},
});
return (
await workflowRunRepository.save({
name: `Execution of ${workflowVersion.name}`,
name: `#${workflowRunCount + 1} - ${workflow.name}`,
workflowVersionId,
createdBy,
workflowId: workflowVersion.workflowId,
workflowId: workflow.id,
status: WorkflowRunStatus.NOT_STARTED,
})
).id;

View File

@ -203,6 +203,7 @@ export {
IconMinus,
IconMoneybag,
IconMoodSmile,
IconMoon,
IconMouse2,
IconNorthStar,
IconNoteOff,
@ -262,6 +263,9 @@ export {
IconSquareRoundedX,
IconStatusChange,
IconStepInto,
IconSun,
IconSunMoon,
IconSwitchHorizontal,
IconTable,
IconTag,
IconTags,
@ -281,16 +285,13 @@ export {
IconUpload,
IconUser,
IconUserCircle,
IconSwitchHorizontal,
IconUserCog,
IconUserPin,
IconUserPlus,
IconSunMoon,
IconMoon,
IconSun,
IconUsers,
IconVariable,
IconVariablePlus,
IconVersions,
IconVideo,
IconWand,
IconWebhook,