-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathobject.tsx
More file actions
85 lines (79 loc) · 2.59 KB
/
Copy pathobject.tsx
File metadata and controls
85 lines (79 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import React from 'react';
import {
WidgetRenderer,
SchemaFieldObject,
WidgetProps
} from '@stac-manager/data-core';
import { useFormikContext } from 'formik';
import { Button } from '@chakra-ui/react';
import { CollecticonPlusSmall } from '@devseed-ui/collecticons-chakra';
import get from 'lodash-es/get';
import { ObjectProperty } from '../components/object-property';
/**
* Finds the next unique value by appending an incrementing number to the given
* value.
*
* @param value - The base value to which the incrementing number will be
* appended.
* @param valueKeys - An array of existing values to check against for
* uniqueness.
* @returns The next unique value that is not present in the valueKeys array.
*/
const findNextValue = (value: string, valueKeys: string[]): string => {
let i = 0;
while (true) {
const v = `${value}-${++i}`;
if (!valueKeys.includes(v)) return v;
}
};
/*****************************************************************************
* C O M P O N E N T *
*****************************************************************************/
export function WidgetObject(props: WidgetProps) {
const { pointer } = props;
const field = props.field as SchemaFieldObject;
const ctx = useFormikContext();
const values = pointer ? get(ctx.values, pointer) : ctx.values;
const schemaKeys = Object.keys(field.properties);
const valueKeys = Object.keys(values || {});
const unlistedKeys = valueKeys.filter((key) => !schemaKeys.includes(key));
return (
<>
{Object.entries(field.properties).map(([key, item]) => (
<WidgetRenderer
key={key}
pointer={pointer ? `${pointer}.${key}` : key}
field={item}
isRequired={field.required?.includes(key)}
/>
))}
{field.additionalProperties && (
<>
{unlistedKeys.map((key) => (
<ObjectProperty
key={key}
property={key}
existentProperties={valueKeys.filter((k) => k !== key)}
pointer={pointer ? `${pointer}.${key}` : key}
/>
))}
<Button
colorPalette='base'
size='sm'
onClick={() => {
const nextKey = findNextValue('property', valueKeys);
ctx.setFieldValue(
pointer ? `${pointer}.${nextKey}` : nextKey,
''
);
}}
aria-label='Add property'
>
<CollecticonPlusSmall />
Add property
</Button>
</>
)}
</>
);
}