Skip to content

Commit 3d5e009

Browse files
authored
fix(Data Mapper): Update Function config panel to fix wrapping, delete logic, placement of action items, info bubble (#6393)
* dm font * fix func config panel * update function config 2 * fix style cherry-pick * add remove logic * fix margin
1 parent dc66ab4 commit 3d5e009

File tree

8 files changed

+163
-126
lines changed

8 files changed

+163
-126
lines changed

libs/data-mapper-v2/src/components/functionConfigurationMenu/inputDropdown/InputDropdown.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ export const InputDropdown = ({
317317
</Option>
318318
)}
319319
</Combobox>
320-
<Caption2>{typeValidationMessage}</Caption2>
320+
<Caption2 className={styles.validationWarningmessage}>{typeValidationMessage}</Caption2>
321321
</Stack>
322322
);
323323
};

libs/data-mapper-v2/src/components/functionConfigurationMenu/inputDropdown/styles.ts

+3
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,7 @@ export const useStyles = makeStyles({
4040
fontSize: '10px',
4141
color: tokens.colorPaletteYellowForeground2,
4242
},
43+
validationWarningmessage: {
44+
fontStyle: 'italic',
45+
},
4346
});

libs/data-mapper-v2/src/components/functionConfigurationMenu/inputTab/InputList.tsx

+9-11
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ export const CustomListItem = (props: CustomListItemProps) => {
138138
} = props;
139139

140140
return (
141-
<ListItem key={`input-${name}`}>
142-
<div className={styles.draggableListItem}>
143-
<span className={styles.inputDropdown}>
141+
<ListItem key={`input-${name}`} className={styles.draggableListItem}>
142+
<div className={styles.draggableListContainer}>
143+
<span className={styles.formControl}>
144144
<InputDropdown
145145
inputAllowsCustomValues={customValueAllowed}
146146
index={index}
@@ -152,14 +152,12 @@ export const CustomListItem = (props: CustomListItemProps) => {
152152
validateAndCreateConnection={validateAndCreateConnection}
153153
/>
154154
</span>
155-
<span className={styles.listButtons}>
156-
<span className={styles.badgeWrapper}>
157-
{type && (
158-
<Badge appearance="filled" color="informative">
159-
{type}
160-
</Badge>
161-
)}
162-
</span>
155+
{type && (
156+
<Badge appearance="filled" color="informative">
157+
{type}
158+
</Badge>
159+
)}
160+
<span>
163161
<Button className={styles.listButton} appearance="transparent" icon={<DeleteRegular />} onClick={remove} />
164162
{draggable && dragHandleProps && (
165163
<Button className={styles.listButton} appearance="transparent" icon={<ReOrderRegular />} {...dragHandleProps} />

libs/data-mapper-v2/src/components/functionConfigurationMenu/inputTab/inputTab.tsx

+85-68
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Badge, Button, Caption1, Caption2, Text } from '@fluentui/react-components';
1+
import { Badge, Button, Caption1, Text } from '@fluentui/react-components';
22
import { AddRegular, DeleteRegular } from '@fluentui/react-icons';
33
import { useDispatch, useSelector } from 'react-redux';
44
import { UnboundedInput } from '../../../constants/FunctionConstants';
@@ -14,7 +14,6 @@ import type { ConnectionDictionary, NodeConnection, CustomValueConnection, Input
1414
import { getInputName, getInputValue } from '../../../utils/Function.Utils';
1515
import type { InputOptionProps } from '../inputDropdown/InputDropdown';
1616
import { InputDropdown } from '../inputDropdown/InputDropdown';
17-
import { useStyles } from './styles';
1817
import { isSchemaNodeExtended } from '../../../utils';
1918
import {
2019
connectionDoesExist,
@@ -28,6 +27,7 @@ import InputListWrapper, { type TemplateItemProps, type CommonProps } from './In
2827
import { useCallback, useMemo } from 'react';
2928
import { useIntl } from 'react-intl';
3029
import { InputCustomInfoLabel } from './inputCustomInfoLabel';
30+
import { useStyles } from './styles';
3131

3232
export const InputTabContents = (props: {
3333
func: FunctionData;
@@ -99,43 +99,50 @@ export const InputTabContents = (props: {
9999
};
100100

101101
return (
102-
<div className={styles.boundedInputRow} key={index}>
103-
<div className={styles.boundedInputTopRow}>
104-
<div className={styles.inputNameDiv}>
105-
<Caption1 className={styles.inputName}>{input.name}</Caption1>
106-
<Caption2>{input.tooltip ?? input.placeHolder ?? ''}</Caption2>
102+
<div className={styles.row} key={index}>
103+
<div className={styles.header}>
104+
<div className={styles.titleContainer}>
105+
<div>
106+
<Caption1 className={styles.titleText}>
107+
{input.name}
108+
<Text className={styles.titleRequiredLabelText}>{input.isOptional ? '' : '*'}</Text>
109+
</Caption1>
110+
<InputCustomInfoLabel />
111+
</div>
112+
<Text className={styles.titleText}>
113+
<span className={styles.titleLabelText}>{resources.ACCEPTED_TYPES}</span>
114+
{input.allowedTypes}
115+
</Text>
116+
</div>
117+
<div className={styles.descriptionContainer}>
118+
<Text className={styles.descriptionText}>{input.tooltip ?? input.placeHolder ?? ''}</Text>
107119
</div>
108-
<Caption2 className={styles.allowedTypesComponent}>
109-
<Text className={styles.typesParent}>{resources.ACCEPTED_TYPES}</Text>
110-
{input.allowedTypes}
111-
</Caption2>
112-
<InputCustomInfoLabel />
113120
</div>
114-
<div>
115-
<span className={styles.inputDropdownWrapper}>
116-
<InputDropdown
117-
index={index}
118-
schemaListType={SchemaType.Source}
119-
functionId={props.functionKey}
120-
currentNode={props.func}
121-
inputName={getInputName(inputConnection, connections)}
122-
inputValue={getInputValue(inputConnection)}
123-
validateAndCreateConnection={validateAndCreateConnection}
124-
/>
125-
</span>
126-
<span className={styles.badgeWrapper}>
121+
<div className={styles.body}>
122+
<div className={styles.formControlWrapper}>
123+
<span className={styles.formControl}>
124+
<InputDropdown
125+
index={index}
126+
schemaListType={SchemaType.Source}
127+
functionId={props.functionKey}
128+
currentNode={props.func}
129+
inputName={getInputName(inputConnection, connections)}
130+
inputValue={getInputValue(inputConnection)}
131+
validateAndCreateConnection={validateAndCreateConnection}
132+
/>
133+
</span>
127134
{inputType && (
128135
<Badge appearance="filled" color="informative">
129136
{inputType}
130137
</Badge>
131138
)}
132-
</span>
133-
<Button
134-
className={styles.listButton}
135-
appearance="transparent"
136-
icon={<DeleteRegular />}
137-
onClick={() => removeConnection(index)}
138-
/>
139+
<Button
140+
className={styles.controlButton}
141+
appearance="transparent"
142+
icon={<DeleteRegular />}
143+
onClick={() => removeConnection(index)}
144+
/>
145+
</div>
139146
</div>
140147
</div>
141148
);
@@ -201,44 +208,54 @@ const UnlimitedInputs = (props: {
201208
);
202209

203210
return (
204-
<div>
205-
<div>
206-
<span className={styles.unlimitedInputHeaderCell} key="input-name">
207-
<Caption1>{`${inputsFromManifest[0].name}${inputsFromManifest[0].isOptional ? ` (${stringResources.OPTIONAL})` : ''}`}</Caption1>
208-
<InputCustomInfoLabel />
209-
</span>
210-
<span className={styles.unlimitedInputHeaderCell} key="input-types">
211-
<Caption2>
212-
<Text className={styles.typesParent}>{stringResources.ACCEPT_TYPES}</Text>
211+
<div className={styles.row}>
212+
<div className={styles.header}>
213+
<div className={styles.titleContainer}>
214+
<div>
215+
<Caption1 className={styles.titleText}>
216+
{inputsFromManifest[0].name}
217+
<Text className={styles.titleRequiredLabelText}>{inputsFromManifest[0].isOptional ? '' : '*'}</Text>
218+
</Caption1>
219+
<InputCustomInfoLabel />
220+
</div>
221+
<Text className={styles.titleText}>
222+
<span className={styles.titleLabelText}>{stringResources.ACCEPT_TYPES}</span>
213223
{inputsFromManifest[0].allowedTypes}
214-
</Caption2>
215-
</span>
224+
</Text>
225+
</div>
226+
<div className={styles.descriptionContainer}>
227+
<Text className={styles.descriptionText}>{inputsFromManifest[0].tooltip ?? inputsFromManifest[0].placeHolder ?? ''}</Text>
228+
</div>
229+
</div>
230+
<div className={styles.body}>
231+
<DraggableList<TemplateItemProps, CommonProps, any>
232+
list={Object.entries(functionConnection.inputs).map((input, index) => ({
233+
input: input[1],
234+
index,
235+
}))}
236+
commonProps={{
237+
functionKey: props.functionKey,
238+
data: props.func,
239+
inputsFromManifest,
240+
connections: props.connections,
241+
schemaType: SchemaType.Source,
242+
draggable: true,
243+
}}
244+
onMoveEnd={onDragMoveEnd}
245+
itemKey={'index'}
246+
template={InputListWrapper}
247+
/>
248+
<div className={styles.formControlDescription}>
249+
<Button
250+
icon={<AddRegular className={styles.addIcon} />}
251+
onClick={() => addUnboundedInputSlot()}
252+
className={styles.addButton}
253+
appearance="subtle"
254+
>
255+
<Caption1>{stringResources.ADD_INPUT}</Caption1>
256+
</Button>
257+
</div>
216258
</div>
217-
<DraggableList<TemplateItemProps, CommonProps, any>
218-
list={Object.entries(functionConnection.inputs).map((input, index) => ({
219-
input: input[1],
220-
index,
221-
}))}
222-
commonProps={{
223-
functionKey: props.functionKey,
224-
data: props.func,
225-
inputsFromManifest,
226-
connections: props.connections,
227-
schemaType: SchemaType.Source,
228-
draggable: true,
229-
}}
230-
onMoveEnd={onDragMoveEnd}
231-
itemKey={'index'}
232-
template={InputListWrapper}
233-
/>
234-
<Button
235-
icon={<AddRegular className={styles.addIcon} />}
236-
onClick={() => addUnboundedInputSlot()}
237-
className={styles.addButton}
238-
appearance="transparent"
239-
>
240-
<Caption1>{stringResources.ADD_INPUT}</Caption1>
241-
</Button>
242259
</div>
243260
);
244261
};
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,77 @@
11
import { makeStyles } from '@fluentui/react-components';
22

33
export const useStyles = makeStyles({
4-
unlimitedInputHeaderCell: {
5-
width: '170px',
6-
display: 'inline-block',
7-
paddingRight: '5px',
8-
},
9-
draggableListItem: {
10-
display: 'inline-block',
4+
row: {
115
width: '100%',
6+
paddingBottom: '20px',
127
},
13-
inputDropdownWrapper: {
14-
display: 'inline-block',
15-
width: '270px',
16-
paddingRight: '8px',
17-
},
18-
inputDropdown: {
19-
width: '220px',
20-
display: 'inline-block',
8+
header: {
9+
display: 'flex',
10+
flexDirection: 'column',
2111
},
22-
boundedInputTopRow: {
12+
titleContainer: {
2313
display: 'flex',
2414
flexDirection: 'row',
25-
height: '40px',
15+
justifyContent: 'space-between',
2616
},
27-
boundedInputRow: {
28-
paddingBottom: '25px',
17+
titleText: {
18+
display: 'inline',
19+
fontSize: '12px',
2920
},
30-
allowedTypesComponent: {
31-
width: '170px',
32-
textAlign: 'end',
21+
titleLabelText: {
22+
fontStyle: 'italic',
3323
},
34-
typesParent: {
35-
fontSize: '14px',
24+
titleRequiredLabelText: {
25+
color: 'red',
3626
},
37-
inputNameDiv: {
38-
width: '200px',
27+
descriptionContainer: {
28+
display: 'flex',
29+
flexDirection: 'row',
30+
width: '60%',
3931
},
40-
inputName: {
41-
display: 'block',
32+
descriptionText: {
33+
display: 'inline',
34+
fontSize: '10px',
4235
},
43-
addButton: {
44-
marginLEft: '0px',
36+
body: {
37+
display: 'flex',
38+
flexDirection: 'column',
4539
},
46-
addIcon: {
47-
fontSize: '12px',
40+
formControlWrapper: {
41+
display: 'flex',
42+
flexDirection: 'row',
43+
justifyContent: 'space-between',
4844
},
49-
tabWrapper: {
50-
paddingTop: '8px',
45+
formControl: {
46+
display: 'inline-block',
47+
width: '60%',
5148
},
52-
listButtons: {
53-
paddingLeft: '8px',
49+
formControlDescription: {
50+
width: '60%',
51+
display: 'block',
52+
marginTop: '15px',
5453
},
55-
badgeWrapper: {
56-
width: '70px',
57-
display: 'inline-block',
54+
controlButton: {
55+
paddingTop: '0px',
5856
},
5957
listButton: {
6058
width: '40px',
6159
maxWidth: '40px',
60+
paddingTop: '0px',
61+
},
62+
addButton: {
63+
paddingLeft: '0px',
64+
},
65+
addIcon: {
66+
fontSize: '12px',
67+
},
68+
draggableListContainer: {
69+
display: 'flex',
70+
flexDirection: 'row',
71+
justifyContent: 'space-between',
72+
},
73+
draggableListItem: {
74+
marginTop: '5px',
75+
maxHeight: 'fit-content',
6276
},
6377
});

libs/data-mapper-v2/src/components/schema/tree/styles.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export const useTreeNodeStyles = makeStyles({
5454
paddingLeft: '16px',
5555
},
5656
sourceSchemaContainer: {
57-
marginRight: '7px',
57+
marginRight: '11px',
5858
},
5959
wrapper: {
6060
display: 'flex',

libs/data-mapper-v2/src/core/state/DataMapSlice.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -475,12 +475,17 @@ export const dataMapSlice = createSlice({
475475
const newConnections = {
476476
...state.curDataMapOperation.dataMapConnections,
477477
};
478-
const inputValueToRemove = newConnections[action.payload.targetId].inputs[action.payload.inputIndex];
479-
if (isEmptyConnection(inputValueToRemove)) {
480-
return;
478+
const { inputIndex, targetId } = action.payload;
479+
const inputs = newConnections[targetId].inputs;
480+
const inputValueToRemove = inputs[inputIndex];
481+
if (!isEmptyConnection(inputValueToRemove)) {
482+
const sourceIdToRemove = isCustomValueConnection(inputValueToRemove) ? inputValueToRemove.value : inputValueToRemove.reactFlowKey;
483+
deleteConnectionFromConnections(newConnections, sourceIdToRemove, targetId, undefined);
481484
}
482-
const sourceIdToRemove = isCustomValueConnection(inputValueToRemove) ? inputValueToRemove.value : inputValueToRemove.reactFlowKey;
483-
deleteConnectionFromConnections(newConnections, sourceIdToRemove, action.payload.targetId, undefined);
485+
486+
// Remove the input completely once it has been emptied
487+
newConnections[targetId].inputs = [...inputs.slice(0, inputIndex), ...inputs.slice(inputIndex + 1)];
488+
484489
doDataMapOperation(
485490
state,
486491
{

0 commit comments

Comments
 (0)