Add suggested values for variable dropdown (#9437)
<img width="378" alt="Capture d’écran 2025-01-07 à 15 37 20" src="https://github.com/user-attachments/assets/c15abcac-684a-4c3b-ad12-62cf91afe927" /> Here is a first version: - simple fields have a suggested value - composite do not, but sub values of composite do - json, arrays or complex values do not
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "twenty-e2e-testing",
|
"name": "twenty-e2e-testing",
|
||||||
"version": "0.40.0-canary",
|
"version": "0.35.4",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "twenty-emails",
|
"name": "twenty-emails",
|
||||||
"version": "0.40.0-canary",
|
"version": "0.35.4",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "twenty-front",
|
"name": "twenty-front",
|
||||||
"version": "0.40.0-canary",
|
"version": "0.35.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ServerlessFunctionExecutionStatus } from '~/generated-metadata/graphql';
|
|
||||||
import { createFamilyState } from '@/ui/utilities/state/utils/createFamilyState';
|
import { createFamilyState } from '@/ui/utilities/state/utils/createFamilyState';
|
||||||
|
import { ServerlessFunctionExecutionStatus } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
export type ServerlessFunctionTestData = {
|
export type ServerlessFunctionTestData = {
|
||||||
input: { [field: string]: any };
|
input: { [field: string]: any };
|
||||||
@ -13,8 +13,7 @@ export type ServerlessFunctionTestData = {
|
|||||||
height: number;
|
height: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_OUTPUT_VALUE =
|
export const DEFAULT_OUTPUT_VALUE = 'Enter an input above then press "Test"';
|
||||||
'Enter an input above then press "run Function"';
|
|
||||||
|
|
||||||
export const serverlessFunctionTestDataFamilyState = createFamilyState<
|
export const serverlessFunctionTestDataFamilyState = createFamilyState<
|
||||||
ServerlessFunctionTestData,
|
ServerlessFunctionTestData,
|
||||||
|
|||||||
@ -145,15 +145,18 @@ export const WorkflowVariablesDropdownFieldItems = ({
|
|||||||
/>
|
/>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
{filteredOptions.map(([key, value]) => (
|
{filteredOptions.map(([key, subStep]) => (
|
||||||
<MenuItemSelect
|
<MenuItemSelect
|
||||||
key={key}
|
key={key}
|
||||||
selected={false}
|
selected={false}
|
||||||
hovered={false}
|
hovered={false}
|
||||||
onClick={() => handleSelectField(key)}
|
onClick={() => handleSelectField(key)}
|
||||||
text={value.label || key}
|
text={subStep.label || key}
|
||||||
hasSubMenu={!value.isLeaf}
|
hasSubMenu={!subStep.isLeaf}
|
||||||
LeftIcon={value.icon ? getIcon(value.icon) : undefined}
|
LeftIcon={subStep.icon ? getIcon(subStep.icon) : undefined}
|
||||||
|
contextualText={
|
||||||
|
subStep.isLeaf ? subStep?.value?.toString() : undefined
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</DropdownMenuItemsContainer>
|
</DropdownMenuItemsContainer>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "twenty-server",
|
"name": "twenty-server",
|
||||||
"version": "0.40.0-canary",
|
"version": "0.35.4",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@ -7,13 +7,16 @@ type FakeValueTypes =
|
|||||||
| Date
|
| Date
|
||||||
| FakeValueTypes[]
|
| FakeValueTypes[]
|
||||||
| FieldMetadataType
|
| FieldMetadataType
|
||||||
| { [key: string]: FakeValueTypes };
|
| { [key: string]: FakeValueTypes }
|
||||||
|
| null;
|
||||||
|
|
||||||
export const generateFakeValue = (valueType: string): FakeValueTypes => {
|
type TypeClassification = 'Primitive' | 'FieldMetadataType';
|
||||||
|
|
||||||
|
const generatePrimitiveValue = (valueType: string): FakeValueTypes => {
|
||||||
if (valueType === 'string') {
|
if (valueType === 'string') {
|
||||||
return 'generated-string-value';
|
return 'My text';
|
||||||
} else if (valueType === 'number') {
|
} else if (valueType === 'number') {
|
||||||
return 1;
|
return 20;
|
||||||
} else if (valueType === 'boolean') {
|
} else if (valueType === 'boolean') {
|
||||||
return true;
|
return true;
|
||||||
} else if (valueType === 'Date') {
|
} else if (valueType === 'Date') {
|
||||||
@ -38,9 +41,51 @@ export const generateFakeValue = (valueType: string): FakeValueTypes => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return objData;
|
return objData;
|
||||||
} else if (valueType === FieldMetadataType.TEXT) {
|
|
||||||
return 'My text';
|
|
||||||
} else {
|
} else {
|
||||||
return 'generated-string-value';
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateFieldMetadataTypeValue = (
|
||||||
|
valueType: string,
|
||||||
|
): FakeValueTypes | null => {
|
||||||
|
// composite types do not need to be generated
|
||||||
|
switch (valueType) {
|
||||||
|
case FieldMetadataType.TEXT:
|
||||||
|
return 'My text';
|
||||||
|
case FieldMetadataType.NUMBER:
|
||||||
|
return 20;
|
||||||
|
case FieldMetadataType.BOOLEAN:
|
||||||
|
return true;
|
||||||
|
case FieldMetadataType.DATE:
|
||||||
|
return '01/23/2025';
|
||||||
|
case FieldMetadataType.DATE_TIME:
|
||||||
|
return '01/23/2025 15:16';
|
||||||
|
case FieldMetadataType.ADDRESS:
|
||||||
|
return '123 Main St, Anytown, CA 12345';
|
||||||
|
case FieldMetadataType.FULL_NAME:
|
||||||
|
return 'Tim Cook';
|
||||||
|
case FieldMetadataType.RAW_JSON:
|
||||||
|
return null;
|
||||||
|
case FieldMetadataType.RICH_TEXT:
|
||||||
|
return 'My rich text';
|
||||||
|
case FieldMetadataType.UUID:
|
||||||
|
return '123e4567-e89b-12d3-a456-426614174000';
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const generateFakeValue = (
|
||||||
|
valueType: string,
|
||||||
|
classification: TypeClassification = 'Primitive',
|
||||||
|
): FakeValueTypes => {
|
||||||
|
switch (classification) {
|
||||||
|
case 'Primitive':
|
||||||
|
return generatePrimitiveValue(valueType);
|
||||||
|
case 'FieldMetadataType':
|
||||||
|
return generateFieldMetadataTypeValue(valueType);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -25,7 +25,7 @@ const generateObjectRecordFields = (
|
|||||||
type: field.type,
|
type: field.type,
|
||||||
icon: field.icon,
|
icon: field.icon,
|
||||||
label: field.label,
|
label: field.label,
|
||||||
value: generateFakeValue(field.type),
|
value: generateFakeValue(field.type, 'FieldMetadataType'),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
acc[field.name] = {
|
acc[field.name] = {
|
||||||
@ -37,7 +37,7 @@ const generateObjectRecordFields = (
|
|||||||
isLeaf: true,
|
isLeaf: true,
|
||||||
type: property.type,
|
type: property.type,
|
||||||
label: camelToTitleCase(property.name),
|
label: camelToTitleCase(property.name),
|
||||||
value: generateFakeValue(property.type),
|
value: generateFakeValue(property.type, 'FieldMetadataType'),
|
||||||
};
|
};
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "twenty-ui",
|
"name": "twenty-ui",
|
||||||
"version": "0.40.0-canary",
|
"version": "0.35.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@ -47,6 +47,7 @@ type MenuItemSelectProps = {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
hovered?: boolean;
|
hovered?: boolean;
|
||||||
hasSubMenu?: boolean;
|
hasSubMenu?: boolean;
|
||||||
|
contextualText?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MenuItemSelect = ({
|
export const MenuItemSelect = ({
|
||||||
@ -59,6 +60,7 @@ export const MenuItemSelect = ({
|
|||||||
disabled,
|
disabled,
|
||||||
hovered,
|
hovered,
|
||||||
hasSubMenu = false,
|
hasSubMenu = false,
|
||||||
|
contextualText,
|
||||||
}: MenuItemSelectProps) => {
|
}: MenuItemSelectProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
@ -73,8 +75,13 @@ export const MenuItemSelect = ({
|
|||||||
aria-selected={selected}
|
aria-selected={selected}
|
||||||
aria-disabled={disabled}
|
aria-disabled={disabled}
|
||||||
>
|
>
|
||||||
<MenuItemLeftContent LeftIcon={LeftIcon} text={text} />
|
<MenuItemLeftContent
|
||||||
|
LeftIcon={LeftIcon}
|
||||||
|
text={text}
|
||||||
|
contextualText={contextualText}
|
||||||
|
/>
|
||||||
{selected && needIconCheck && <IconCheck size={theme.icon.size.md} />}
|
{selected && needIconCheck && <IconCheck size={theme.icon.size.md} />}
|
||||||
|
|
||||||
{hasSubMenu && (
|
{hasSubMenu && (
|
||||||
<IconChevronRight
|
<IconChevronRight
|
||||||
size={theme.icon.size.sm}
|
size={theme.icon.size.sm}
|
||||||
|
|||||||
@ -14,6 +14,10 @@ import {
|
|||||||
StyledMenuItemLeftContent,
|
StyledMenuItemLeftContent,
|
||||||
} from './StyledMenuItemBase';
|
} from './StyledMenuItemBase';
|
||||||
|
|
||||||
|
const StyledMainText = styled.div`
|
||||||
|
flex-shrink: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
const StyledContextualText = styled.div`
|
const StyledContextualText = styled.div`
|
||||||
color: ${({ theme }) => theme.color.gray35};
|
color: ${({ theme }) => theme.color.gray35};
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
@ -29,6 +33,7 @@ const StyledContextualText = styled.div`
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
padding-left: ${({ theme }) => theme.spacing(1)};
|
padding-left: ${({ theme }) => theme.spacing(1)};
|
||||||
|
flex-shrink: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type MenuItemLeftContentProps = {
|
type MenuItemLeftContentProps = {
|
||||||
@ -67,7 +72,13 @@ export const MenuItemLeftContent = ({
|
|||||||
<LeftIcon size={theme.icon.size.md} stroke={theme.icon.stroke.sm} />
|
<LeftIcon size={theme.icon.size.md} stroke={theme.icon.stroke.sm} />
|
||||||
)}
|
)}
|
||||||
<StyledMenuItemLabel hasLeftIcon={!!LeftIcon}>
|
<StyledMenuItemLabel hasLeftIcon={!!LeftIcon}>
|
||||||
{isString(text) ? <OverflowingTextWithTooltip text={text} /> : text}
|
{isString(text) ? (
|
||||||
|
<StyledMainText>
|
||||||
|
<OverflowingTextWithTooltip text={text} />
|
||||||
|
</StyledMainText>
|
||||||
|
) : (
|
||||||
|
text
|
||||||
|
)}
|
||||||
{isString(contextualText) ? (
|
{isString(contextualText) ? (
|
||||||
<StyledContextualText>{`· ${contextualText}`}</StyledContextualText>
|
<StyledContextualText>{`· ${contextualText}`}</StyledContextualText>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "twenty-website",
|
"name": "twenty-website",
|
||||||
"version": "0.40.0-canary",
|
"version": "0.35.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"nx": "NX_DEFAULT_PROJECT=twenty-website node ../../node_modules/nx/bin/nx.js",
|
"nx": "NX_DEFAULT_PROJECT=twenty-website node ../../node_modules/nx/bin/nx.js",
|
||||||
|
|||||||
Reference in New Issue
Block a user