Skip to content

Commit e73c63d

Browse files
authored
Fix array object (#30)
1 parent fa58210 commit e73c63d

File tree

10 files changed

+167
-74
lines changed

10 files changed

+167
-74
lines changed

src/lib/core/types/specs.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ export interface ObjectSpec<LinkType = any> {
8383
layoutOpen?: boolean;
8484
order?: string[];
8585
link?: LinkType;
86-
showOptional?: boolean;
8786
};
8887
}
8988

src/lib/kit/components/Inputs/ObjectBase/ObjectBase.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export const ObjectBase: ObjectIndependentInput = ({spec, name, Layout, ...restP
5757
return null;
5858
}
5959

60-
if (!restProps.input.value && !spec.viewSpec.showOptional) {
60+
if (!restProps.input.value) {
6161
return addBtn;
6262
}
6363

src/lib/kit/components/Inputs/ObjectValueInput/ObjectValueInput.tsx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@ import {Controller, FieldValue, ObjectIndependentInput, ValidateError} from '../
66

77
const OBJECT_VALUE_PROPERTY_NAME = 'value';
88

9-
export const ObjectValueInput: ObjectIndependentInput = ({spec, input, name}) => {
9+
export const ObjectValueInput: ObjectIndependentInput = (props) => {
10+
const {spec, input, name, Layout} = props;
11+
1012
const parentOnChange = React.useCallback(
1113
(childName: string, childValue: FieldValue, childErrors?: Record<string, ValidateError>) =>
1214
input.onChange(
1315
(currentValue) =>
14-
_.set(
15-
{...(currentValue || {})},
16-
childName.split(`${name}.`).join(''),
17-
childValue,
18-
),
16+
_.set({...currentValue}, childName.split(`${name}.`).join(''), childValue),
1917
childErrors,
2018
),
2119
[input.onChange, input.name],
@@ -26,20 +24,36 @@ export const ObjectValueInput: ObjectIndependentInput = ({spec, input, name}) =>
2624
[input.onChange],
2725
);
2826

29-
const specProperties = {...spec.properties};
27+
const childSpec = React.useMemo(() => {
28+
if (spec.properties?.[OBJECT_VALUE_PROPERTY_NAME]) {
29+
const childSpec = _.cloneDeep(spec.properties[OBJECT_VALUE_PROPERTY_NAME]);
30+
31+
childSpec.viewSpec.layout = '';
32+
33+
return childSpec;
34+
}
35+
36+
return undefined;
37+
}, [spec.properties]);
3038

31-
if (!specProperties[OBJECT_VALUE_PROPERTY_NAME]) {
39+
if (!childSpec) {
3240
return null;
3341
}
3442

35-
return (
43+
const content = (
3644
<Controller
3745
initialValue={input.value?.[OBJECT_VALUE_PROPERTY_NAME]}
38-
spec={specProperties[OBJECT_VALUE_PROPERTY_NAME]}
46+
spec={childSpec}
3947
name={`${name}.${OBJECT_VALUE_PROPERTY_NAME}`}
4048
key={`${name}.${OBJECT_VALUE_PROPERTY_NAME}`}
4149
parentOnChange={parentOnChange}
4250
parentOnUnmount={parentOnUnmount}
4351
/>
4452
);
53+
54+
if (Layout) {
55+
return <Layout {...props}>{content}</Layout>;
56+
}
57+
58+
return <React.Fragment>{content}</React.Fragment>;
4559
};

src/lib/kit/components/Inputs/Secret/Secret.tsx

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,25 @@ import React from 'react';
22

33
import _ from 'lodash';
44

5-
import {
6-
Controller,
7-
FieldValue,
8-
ObjectIndependentInput,
9-
Spec,
10-
ValidateError,
11-
} from '../../../../core';
5+
import {Controller, FieldValue, ObjectIndependentInput, ValidateError} from '../../../../core';
126

137
const SECRET_PROPERTY_NAME = 'raw';
148

15-
export const Secret: ObjectIndependentInput = ({spec, name, input}) => {
9+
export const Secret: ObjectIndependentInput = (props) => {
10+
const {spec, name, input, Layout} = props;
11+
12+
const childSpec = React.useMemo(() => {
13+
if (spec.properties?.[SECRET_PROPERTY_NAME]) {
14+
const childSpec = _.cloneDeep(spec.properties?.[SECRET_PROPERTY_NAME]);
15+
16+
childSpec.viewSpec.layout = '';
17+
18+
return childSpec;
19+
}
20+
21+
return undefined;
22+
}, [spec.properties]);
23+
1624
const parentOnChange = React.useCallback(
1725
(childName: string, childValue: FieldValue, childErrors?: Record<string, ValidateError>) =>
1826
input.onChange(
@@ -32,24 +40,24 @@ export const Secret: ObjectIndependentInput = ({spec, name, input}) => {
3240
[input.onChange],
3341
);
3442

35-
if (!_.isObjectLike(spec.properties)) {
36-
return null;
37-
}
38-
39-
const specProperties = {...spec.properties} as Record<string, Spec>;
40-
41-
if (!specProperties[SECRET_PROPERTY_NAME]) {
43+
if (!childSpec) {
4244
return null;
4345
}
4446

45-
return (
47+
const content = (
4648
<Controller
4749
initialValue={input.value?.[SECRET_PROPERTY_NAME]}
48-
spec={specProperties[SECRET_PROPERTY_NAME]}
50+
spec={childSpec}
4951
name={`${name}.${SECRET_PROPERTY_NAME}`}
5052
parentOnChange={parentOnChange}
5153
parentOnUnmount={parentOnUnmount}
5254
key={`${name}.${SECRET_PROPERTY_NAME}`}
5355
/>
5456
);
57+
58+
if (Layout) {
59+
return <Layout {...props}>{content}</Layout>;
60+
}
61+
62+
return <React.Fragment>{content}</React.Fragment>;
5563
};

src/lib/kit/components/Inputs/TextLink/TextLink.tsx

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ import {
1212

1313
const TEXT_LINK_PROPERTY_NAME = 'text';
1414

15-
export const TextLink: ObjectIndependentInput = ({spec, input, name}) => {
15+
export const TextLink: ObjectIndependentInput = (props) => {
16+
const {spec, input, name, Layout} = props;
17+
1618
const parentOnChange = React.useCallback(
1719
(childName: string, childValue: FieldValue, childErrors?: Record<string, ValidateError>) =>
1820
input.onChange(
@@ -28,23 +30,39 @@ export const TextLink: ObjectIndependentInput = ({spec, input, name}) => {
2830
[input.onChange],
2931
);
3032

31-
const specProperties = {...spec.properties};
33+
const childSpec = React.useMemo(() => {
34+
if (
35+
spec.properties?.[TEXT_LINK_PROPERTY_NAME] &&
36+
isStringSpec(spec.properties[TEXT_LINK_PROPERTY_NAME])
37+
) {
38+
const childSpec = _.cloneDeep(spec.properties[TEXT_LINK_PROPERTY_NAME]);
39+
40+
childSpec.viewSpec.layout = '';
41+
42+
return childSpec;
43+
}
44+
45+
return undefined;
46+
}, [spec.properties]);
3247

33-
if (
34-
!specProperties[TEXT_LINK_PROPERTY_NAME] ||
35-
!isStringSpec(specProperties[TEXT_LINK_PROPERTY_NAME])
36-
) {
48+
if (!childSpec) {
3749
return null;
3850
}
3951

40-
return (
52+
const content = (
4153
<Controller
4254
initialValue={input.value?.[TEXT_LINK_PROPERTY_NAME]}
43-
spec={specProperties[TEXT_LINK_PROPERTY_NAME]}
55+
spec={childSpec}
4456
name={`${name}.${TEXT_LINK_PROPERTY_NAME}`}
4557
key={`${name}.${TEXT_LINK_PROPERTY_NAME}`}
4658
parentOnChange={parentOnChange}
4759
parentOnUnmount={parentOnUnmount}
4860
/>
4961
);
62+
63+
if (Layout) {
64+
return <Layout {...props}>{content}</Layout>;
65+
}
66+
67+
return <React.Fragment>{content}</React.Fragment>;
5068
};
Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,39 @@
11
import React from 'react';
22

3+
import _ from 'lodash';
4+
35
import {ObjectIndependentView, ViewController} from '../../../../core';
46

57
const OBJECT_VALUE_PROPERTY_NAME = 'value';
68

7-
export const ObjectValueInputView: ObjectIndependentView = ({spec, name}) => {
8-
const specProperties = {...spec.properties};
9+
export const ObjectValueInputView: ObjectIndependentView = ({spec, name, Layout, ...restProps}) => {
10+
const childSpec = React.useMemo(() => {
11+
if (spec.properties?.[OBJECT_VALUE_PROPERTY_NAME]) {
12+
const childSpec = _.cloneDeep(spec.properties[OBJECT_VALUE_PROPERTY_NAME]);
13+
14+
childSpec.viewSpec.layout = '';
15+
16+
return childSpec;
17+
}
18+
19+
return undefined;
20+
}, [spec.properties]);
921

10-
if (!specProperties[OBJECT_VALUE_PROPERTY_NAME]) {
22+
if (!childSpec) {
1123
return null;
1224
}
1325

14-
return (
15-
<ViewController
16-
spec={specProperties[OBJECT_VALUE_PROPERTY_NAME]}
17-
name={`${name}.${OBJECT_VALUE_PROPERTY_NAME}`}
18-
/>
26+
const content = (
27+
<ViewController spec={childSpec} name={`${name}.${OBJECT_VALUE_PROPERTY_NAME}`} />
1928
);
29+
30+
if (Layout) {
31+
return (
32+
<Layout spec={spec} name={name} {...restProps}>
33+
{content}
34+
</Layout>
35+
);
36+
}
37+
38+
return <React.Fragment>{content}</React.Fragment>;
2039
};

src/lib/kit/components/Views/TextLinkView/TextLinkView.tsx

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,40 @@ import React from 'react';
22

33
import _ from 'lodash';
44

5-
import {ObjectIndependentView, ViewController} from '../../../../core';
5+
import {ObjectIndependentView, ViewController, isStringSpec} from '../../../../core';
66

77
const TEXT_LINK_PROPERTY_NAME = 'text';
88

9-
export const TextLinkView: ObjectIndependentView = ({value, spec, name}) => {
10-
const specProperties = spec.properties;
11-
12-
const preparedSpec = React.useMemo(
13-
() =>
14-
specProperties && specProperties[TEXT_LINK_PROPERTY_NAME]
15-
? {
16-
...specProperties[TEXT_LINK_PROPERTY_NAME],
17-
viewSpec: {
18-
...specProperties[TEXT_LINK_PROPERTY_NAME]?.viewSpec,
19-
link: value?.link,
20-
},
21-
}
22-
: undefined,
23-
[specProperties, value?.link],
24-
);
25-
26-
return preparedSpec ? (
27-
<ViewController spec={preparedSpec} name={`${name}.${TEXT_LINK_PROPERTY_NAME}`} />
28-
) : null;
9+
export const TextLinkView: ObjectIndependentView = ({value, spec, name, Layout, ...restProps}) => {
10+
const childSpec = React.useMemo(() => {
11+
if (
12+
spec.properties?.[TEXT_LINK_PROPERTY_NAME] &&
13+
isStringSpec(spec.properties[TEXT_LINK_PROPERTY_NAME])
14+
) {
15+
const childSpec = _.cloneDeep(spec.properties[TEXT_LINK_PROPERTY_NAME]);
16+
17+
childSpec.viewSpec.layout = '';
18+
childSpec.viewSpec.link = value?.link;
19+
20+
return childSpec;
21+
}
22+
23+
return undefined;
24+
}, [spec.properties, value?.link]);
25+
26+
if (!childSpec || !value?.text) {
27+
return null;
28+
}
29+
30+
const content = <ViewController spec={childSpec} name={`${name}.${TEXT_LINK_PROPERTY_NAME}`} />;
31+
32+
if (Layout) {
33+
return (
34+
<Layout spec={spec} name={name} value={value} {...restProps}>
35+
{content}
36+
</Layout>
37+
);
38+
}
39+
40+
return <React.Fragment>{content}</React.Fragment>;
2941
};

src/stories/ObjectSecret.stories.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,24 @@ const baseSpec: ObjectSpec = {
1616
properties: {
1717
raw: {
1818
type: SpecTypes.String,
19-
viewSpec: {type: 'base', layout: 'row', layoutTitle: 'Secret'},
19+
viewSpec: {type: 'base'},
2020
},
2121
},
2222
viewSpec: {
2323
type: 'secret',
24+
layout: 'row',
25+
layoutTitle: 'Secret',
2426
},
2527
};
2628

27-
const excludeOptions = ['description', 'validator', 'viewSpec'];
29+
const excludeOptions = [
30+
'description',
31+
'validator',
32+
'viewSpec.type',
33+
'viewSpec.order',
34+
'viewSpec.layoutOpen',
35+
'viewSpec.disabled',
36+
];
2837

2938
const template = (spec: ObjectSpec = baseSpec) => {
3039
const Template: ComponentStory<typeof SecretBase> = (__, {viewMode}) => (

src/stories/ObjectTextLink.stories.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,27 @@ const baseSpec: ObjectSpec = {
1818
type: SpecTypes.String,
1919
viewSpec: {
2020
type: 'base',
21-
layout: 'row',
22-
layoutTitle: 'Text Link',
2321
placeholder: 'placeholder text',
2422
},
2523
},
2624
},
2725
viewSpec: {
2826
type: 'text_link',
27+
layout: 'row',
28+
layoutTitle: 'Text Link',
2929
},
3030
};
3131

3232
const value = {link: 'https://gravity-ui.com'};
3333

34-
const excludeOptions = ['description', 'validator', 'viewSpec', 'required'];
34+
const excludeOptions = [
35+
'description',
36+
'validator',
37+
'viewSpec.type',
38+
'viewSpec.order',
39+
'viewSpec.layoutOpen',
40+
'viewSpec.disabled',
41+
];
3542

3643
const template = (spec: ObjectSpec = baseSpec) => {
3744
const Template: ComponentStory<typeof TextLinkBase> = (__, {viewMode}) => (

0 commit comments

Comments
 (0)