Skip to content

Commit bb1837f

Browse files
authored
feat: Add type mismatch warning when quick-adding entry to Cloud Config array parameter (#2875)
1 parent cfd0bce commit bb1837f

File tree

2 files changed

+116
-10
lines changed

2 files changed

+116
-10
lines changed

src/dashboard/Data/Config/AddArrayEntryDialog.react.js

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,17 @@ import Label from 'components/Label/Label.react';
1010
import Modal from 'components/Modal/Modal.react';
1111
import React from 'react';
1212
import TextInput from 'components/TextInput/TextInput.react';
13+
import Checkbox from 'components/Checkbox/Checkbox.react';
1314

1415
export default class AddArrayEntryDialog extends React.Component {
1516
constructor() {
1617
super();
17-
this.state = { value: '' };
18+
this.state = {
19+
value: '',
20+
showMismatchRow: false,
21+
mismatchConfirmed: false,
22+
parsedType: '',
23+
};
1824
this.inputRef = React.createRef();
1925
}
2026

@@ -24,9 +30,6 @@ export default class AddArrayEntryDialog extends React.Component {
2430
}
2531
}
2632

27-
valid() {
28-
return this.state.value !== '';
29-
}
3033

3134
getValue() {
3235
try {
@@ -36,17 +39,66 @@ export default class AddArrayEntryDialog extends React.Component {
3639
}
3740
}
3841

42+
getType(value) {
43+
if (Array.isArray(value)) {
44+
return 'array';
45+
}
46+
if (value === null) {
47+
return 'null';
48+
}
49+
return typeof value;
50+
}
51+
52+
handleConfirm() {
53+
const parsed = this.getValue();
54+
const entryType = this.getType(parsed);
55+
const lastType = this.props.lastType;
56+
57+
if (lastType && entryType !== lastType) {
58+
if (!this.state.showMismatchRow) {
59+
this.setState(
60+
{
61+
showMismatchRow: true,
62+
mismatchConfirmed: false,
63+
parsedType: entryType,
64+
},
65+
() => {
66+
if (document.activeElement instanceof HTMLElement) {
67+
document.activeElement.blur();
68+
}
69+
}
70+
);
71+
return;
72+
}
73+
if (!this.state.mismatchConfirmed) {
74+
return;
75+
}
76+
}
77+
78+
this.props.onConfirm(parsed);
79+
this.setState({
80+
value: '',
81+
showMismatchRow: false,
82+
mismatchConfirmed: false,
83+
parsedType: '',
84+
});
85+
}
86+
3987
render() {
40-
return (
88+
const confirmDisabled =
89+
this.state.value === '' ||
90+
(this.state.showMismatchRow && !this.state.mismatchConfirmed);
91+
92+
const addEntryModal = (
4193
<Modal
4294
type={Modal.Types.INFO}
4395
icon="plus-solid"
4496
title="Add entry"
4597
confirmText="Add Unique"
4698
cancelText="Cancel"
4799
onCancel={this.props.onCancel}
48-
onConfirm={() => this.props.onConfirm(this.getValue())}
49-
disabled={!this.valid()}
100+
onConfirm={this.handleConfirm.bind(this)}
101+
disabled={confirmDisabled}
50102
>
51103
<Field
52104
label={
@@ -60,11 +112,39 @@ export default class AddArrayEntryDialog extends React.Component {
60112
placeholder={'Enter value'}
61113
ref={this.inputRef}
62114
value={this.state.value}
63-
onChange={value => this.setState({ value })}
115+
onChange={value =>
116+
this.setState({
117+
value,
118+
showMismatchRow: false,
119+
mismatchConfirmed: false,
120+
})
121+
}
64122
/>
65123
}
66124
/>
125+
{this.state.showMismatchRow && (
126+
<Field
127+
label={
128+
<Label
129+
text="⚠️ Ignore type mismatch"
130+
description={
131+
<>
132+
Previous item type is <strong>{this.props.lastType}</strong>, new entry type is <strong>{this.state.parsedType}</strong>.
133+
</>
134+
}
135+
/>
136+
}
137+
input={
138+
<Checkbox
139+
checked={this.state.mismatchConfirmed}
140+
onChange={checked => this.setState({ mismatchConfirmed: checked })}
141+
/>
142+
}
143+
/>
144+
)}
67145
</Modal>
68146
);
147+
148+
return addEntryModal;
69149
}
70150
}

src/dashboard/Data/Config/Config.react.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class Config extends TableView {
4848
lastNote: null,
4949
showAddEntryDialog: false,
5050
addEntryParam: '',
51+
addEntryLastType: null,
5152
};
5253
this.noteTimeout = null;
5354
}
@@ -122,6 +123,7 @@ class Config extends TableView {
122123
onConfirm={value =>
123124
this.addArrayEntry(this.state.addEntryParam, value)
124125
}
126+
lastType={this.state.addEntryLastType}
125127
/>
126128
);
127129
}
@@ -207,6 +209,16 @@ class Config extends TableView {
207209
};
208210
}
209211

212+
getEntryType(value) {
213+
if (Array.isArray(value)) {
214+
return 'array';
215+
}
216+
if (value === null) {
217+
return 'null';
218+
}
219+
return typeof value;
220+
}
221+
210222
renderRow(data) {
211223
// Parse modal data
212224
const { value, modalValue, type } = this.parseValueForModal(data.value);
@@ -491,11 +503,25 @@ class Config extends TableView {
491503
}
492504

493505
openAddEntryDialog(param) {
494-
this.setState({ showAddEntryDialog: true, addEntryParam: param });
506+
const params = this.props.config.data.get('params');
507+
const arr = params?.get(param);
508+
let lastType = null;
509+
if (Array.isArray(arr) && arr.length > 0) {
510+
lastType = this.getEntryType(arr[arr.length - 1]);
511+
}
512+
this.setState({
513+
showAddEntryDialog: true,
514+
addEntryParam: param,
515+
addEntryLastType: lastType,
516+
});
495517
}
496518

497519
closeAddEntryDialog() {
498-
this.setState({ showAddEntryDialog: false, addEntryParam: '' });
520+
this.setState({
521+
showAddEntryDialog: false,
522+
addEntryParam: '',
523+
addEntryLastType: null,
524+
});
499525
}
500526

501527
async addArrayEntry(param, value) {

0 commit comments

Comments
 (0)