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:
@ -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: [
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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>
|
||||
</>
|
||||
|
||||
@ -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)};
|
||||
|
||||
@ -14,7 +14,7 @@ export const workflowRunsAllView = (
|
||||
type: 'table',
|
||||
key: 'INDEX',
|
||||
position: 0,
|
||||
icon: 'IconHistory',
|
||||
icon: 'IconHistoryToggle',
|
||||
openRecordIn: ViewOpenRecordInType.RECORD_PAGE,
|
||||
kanbanFieldMetadataId: '',
|
||||
filters: [],
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
Reference in New Issue
Block a user