Skip to content

Commit 799c810

Browse files
author
Bob Strahan
committed
Merge branch 'develop' of ssh.gitlab.aws.dev:genaiic-reusable-assets/engagement-artifacts/genaiic-idp-accelerator into develop
2 parents bd1662e + 6d5a3be commit 799c810

File tree

4 files changed

+124
-68
lines changed

4 files changed

+124
-68
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ SPDX-License-Identifier: MIT-0
77

88
### Added
99

10+
### Fixed
11+
1012
## [0.4.3]
1113

1214
### Fixed
@@ -20,6 +22,11 @@ SPDX-License-Identifier: MIT-0
2022
- Evaluation Configuration Robustness
2123
- Improved JSON Schema error messages with actionable diagnostics when configuration issues occur
2224
- Added automatic type coercion for numeric constraints (e.g., `maxItems: "7"``maxItems: 7`) to handle common YAML parsing quirks gracefully
25+
- UI: Document Schema Editor Input Field Fixes
26+
- Fixed Examples, Default Value, Const, and Enum Values fields not allowing first character deletion or comma input
27+
- Fixed Enum field remaining disabled after clearing Const value
28+
- Fixed "Clear all enum values" button not working
29+
- Fixed empty Evaluation Method picklist for Array[String] and other simple array types
2330

2431
### Templates
2532
- us-west-2: `https://s3.us-west-2.amazonaws.com/aws-ml-blog-us-west-2/artifacts/genai-idp/idp-main_0.4.3.yaml`

src/ui/src/components/json-schema-builder/SchemaInspector.jsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,14 @@ const SchemaInspector = ({
436436
}
437437
// Methods with validFor restrictions
438438
if (opt.validFor) {
439-
// For arrays, check if method is valid for arrays
440-
if (selectedAttribute.type === 'array') {
439+
// For arrays with SIMPLE items (Array[String], Array[Number], etc.)
440+
// check if method is valid for the ITEM type
441+
if (selectedAttribute.type === 'array' && !isStructuredArray) {
442+
const itemType = selectedAttribute.items?.type || 'string';
443+
return opt.validFor.includes(itemType);
444+
}
445+
// For structured arrays (Array[Object]), check if method is valid for arrays
446+
if (selectedAttribute.type === 'array' && isStructuredArray) {
441447
return opt.validFor.includes('array');
442448
}
443449
// For other types, check directly

src/ui/src/components/json-schema-builder/constraints/MetadataFields.jsx

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,58 @@
1-
import React from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import PropTypes from 'prop-types';
33
import { FormField, Textarea, Input } from '@cloudscape-design/components';
44
import { formatValueForInput, parseInputValue } from '../utils/schemaHelpers';
55

66
const MetadataFields = ({ attribute, onUpdate }) => {
7+
// Local state for buffering user input without immediate parsing
8+
const [examplesInput, setExamplesInput] = useState('');
9+
const [defaultValueInput, setDefaultValueInput] = useState('');
10+
11+
// Initialize local state from attribute values
12+
useEffect(() => {
13+
if (!attribute.examples) {
14+
setExamplesInput('');
15+
} else if (Array.isArray(attribute.examples)) {
16+
setExamplesInput(attribute.examples.map((ex) => (typeof ex === 'object' ? JSON.stringify(ex) : ex)).join(', '));
17+
}
18+
}, [attribute.examples]);
19+
20+
useEffect(() => {
21+
setDefaultValueInput(formatValueForInput(attribute.default));
22+
}, [attribute.default]);
23+
24+
// Handle Examples field blur - parse and update parent state
25+
const handleExamplesBlur = () => {
26+
if (!examplesInput.trim()) {
27+
const updates = { ...attribute };
28+
delete updates.examples;
29+
onUpdate(updates);
30+
return;
31+
}
32+
try {
33+
const parsed = JSON.parse(`[${examplesInput}]`);
34+
onUpdate({ examples: parsed });
35+
} catch {
36+
const examples = examplesInput
37+
.split(',')
38+
.map((v) => v.trim())
39+
.filter((v) => v);
40+
onUpdate({ examples: examples.length > 0 ? examples : undefined });
41+
}
42+
};
43+
44+
// Handle Default Value field blur - parse and update parent state
45+
const handleDefaultValueBlur = () => {
46+
if (!defaultValueInput) {
47+
const updates = { ...attribute };
48+
delete updates.default;
49+
onUpdate(updates);
50+
return;
51+
}
52+
const parsed = parseInputValue(defaultValueInput, attribute.type);
53+
onUpdate({ default: parsed });
54+
};
55+
756
return (
857
<>
958
<FormField
@@ -23,29 +72,9 @@ const MetadataFields = ({ attribute, onUpdate }) => {
2372
description="Provide example values to guide extraction. This helps the LLM understand the expected format and content. Enter comma-separated values or a JSON array."
2473
>
2574
<Textarea
26-
value={(() => {
27-
if (!attribute.examples) return '';
28-
if (!Array.isArray(attribute.examples)) return '';
29-
return attribute.examples.map((ex) => (typeof ex === 'object' ? JSON.stringify(ex) : ex)).join(', ');
30-
})()}
31-
onChange={({ detail }) => {
32-
if (!detail.value.trim()) {
33-
const updates = { ...attribute };
34-
delete updates.examples;
35-
onUpdate(updates);
36-
return;
37-
}
38-
try {
39-
const parsed = JSON.parse(`[${detail.value}]`);
40-
onUpdate({ examples: parsed });
41-
} catch {
42-
const examples = detail.value
43-
.split(',')
44-
.map((v) => v.trim())
45-
.filter((v) => v);
46-
onUpdate({ examples: examples.length > 0 ? examples : undefined });
47-
}
48-
}}
75+
value={examplesInput}
76+
onChange={({ detail }) => setExamplesInput(detail.value)}
77+
onBlur={handleExamplesBlur}
4978
rows={2}
5079
placeholder='e.g., "INV-2024-001", "PO-12345" or ["John Doe", "Jane Smith"]'
5180
/>
@@ -56,17 +85,9 @@ const MetadataFields = ({ attribute, onUpdate }) => {
5685
description="Fallback value to use if this field is not found or cannot be extracted from the document."
5786
>
5887
<Input
59-
value={formatValueForInput(attribute.default)}
60-
onChange={({ detail }) => {
61-
if (!detail.value) {
62-
const updates = { ...attribute };
63-
delete updates.default;
64-
onUpdate(updates);
65-
return;
66-
}
67-
const parsed = parseInputValue(detail.value, attribute.type);
68-
onUpdate({ default: parsed });
69-
}}
88+
value={defaultValueInput}
89+
onChange={({ detail }) => setDefaultValueInput(detail.value)}
90+
onBlur={handleDefaultValueBlur}
7091
placeholder="e.g., 0, N/A, or a JSON value"
7192
/>
7293
</FormField>

src/ui/src/components/json-schema-builder/constraints/ValueConstraints.jsx

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,63 @@
1-
import React from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import PropTypes from 'prop-types';
33
import { Header, FormField, Input, TokenGroup, Button, SpaceBetween } from '@cloudscape-design/components';
44
import { formatValueForInput, parseInputValue } from '../utils/schemaHelpers';
55

66
const ValueConstraints = ({ attribute, onUpdate }) => {
7+
// Local state for buffering user input without immediate parsing
8+
const [constInput, setConstInput] = useState('');
9+
const [enumInput, setEnumInput] = useState('');
10+
11+
// Initialize local state from attribute values
12+
useEffect(() => {
13+
setConstInput(formatValueForInput(attribute.const));
14+
}, [attribute.const]);
15+
16+
// Initialize enum input as empty (it's only shown when no enum exists yet)
17+
useEffect(() => {
18+
if (!attribute.enum || attribute.enum.length === 0) {
19+
setEnumInput('');
20+
}
21+
}, [attribute.enum]);
22+
23+
// Handle Const field blur - parse and update parent state
24+
const handleConstBlur = () => {
25+
if (!constInput) {
26+
onUpdate({ const: undefined });
27+
return;
28+
}
29+
const parsed = parseInputValue(constInput, attribute.type);
30+
onUpdate({ const: parsed });
31+
};
32+
33+
// Handle Enum field blur - parse and update parent state
34+
const handleEnumBlur = () => {
35+
const value = enumInput.trim();
36+
if (value) {
37+
try {
38+
const parsed = JSON.parse(`[${value}]`);
39+
onUpdate({ enum: parsed });
40+
} catch {
41+
const enumValues = value
42+
.split(',')
43+
.map((v) => v.trim())
44+
.filter((v) => v);
45+
onUpdate({ enum: enumValues.length > 0 ? enumValues : undefined });
46+
}
47+
// Clear the input after successful processing
48+
setEnumInput('');
49+
}
50+
};
51+
752
return (
853
<>
954
<Header variant="h4">Value Constraints</Header>
1055

1156
<FormField label="Const (Single Constant Value)" description="Field must be exactly this value">
1257
<Input
13-
value={formatValueForInput(attribute.const)}
14-
onChange={({ detail }) => {
15-
if (!detail.value) {
16-
const updates = { ...attribute };
17-
delete updates.const;
18-
onUpdate(updates);
19-
return;
20-
}
21-
const parsed = parseInputValue(detail.value, attribute.type);
22-
onUpdate({ const: parsed });
23-
}}
58+
value={constInput}
59+
onChange={({ detail }) => setConstInput(detail.value)}
60+
onBlur={handleConstBlur}
2461
placeholder='e.g., "active", 42, or JSON value'
2562
disabled={attribute.enum && attribute.enum.length > 0}
2663
/>
@@ -46,9 +83,7 @@ const ValueConstraints = ({ attribute, onUpdate }) => {
4683
<Button
4784
variant="link"
4885
onClick={() => {
49-
const updates = { ...attribute };
50-
delete updates.enum;
51-
onUpdate(updates);
86+
onUpdate({ enum: undefined });
5287
}}
5388
>
5489
Clear all enum values
@@ -57,22 +92,9 @@ const ValueConstraints = ({ attribute, onUpdate }) => {
5792
) : (
5893
<Input
5994
placeholder="value1, value2, value3"
60-
defaultValue=""
61-
onBlur={(e) => {
62-
const value = e.target.value.trim();
63-
if (value) {
64-
try {
65-
const parsed = JSON.parse(`[${value}]`);
66-
onUpdate({ enum: parsed });
67-
} catch {
68-
const enumValues = value
69-
.split(',')
70-
.map((v) => v.trim())
71-
.filter((v) => v);
72-
onUpdate({ enum: enumValues.length > 0 ? enumValues : undefined });
73-
}
74-
}
75-
}}
95+
value={enumInput}
96+
onChange={({ detail }) => setEnumInput(detail.value)}
97+
onBlur={handleEnumBlur}
7698
disabled={attribute.const !== undefined}
7799
/>
78100
)}

0 commit comments

Comments
 (0)