datajunction-ui 0.0.12 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Custom metadata field component for nodes
|
|
3
3
|
*/
|
|
4
|
-
import { ErrorMessage, Field } from 'formik';
|
|
5
|
-
import
|
|
4
|
+
import { ErrorMessage, Field, useFormikContext } from 'formik';
|
|
5
|
+
import CodeMirror from '@uiw/react-codemirror';
|
|
6
|
+
import { langs } from '@uiw/codemirror-extensions-langs';
|
|
7
|
+
import { useState, useEffect } from 'react';
|
|
8
|
+
|
|
9
|
+
export const CustomMetadataField = ({ value }) => {
|
|
10
|
+
const formik = useFormikContext();
|
|
11
|
+
const jsonExt = langs.json();
|
|
12
|
+
const [hasError, setHasError] = useState(false);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (!value || value === '') {
|
|
16
|
+
setHasError(false);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const stringValue =
|
|
21
|
+
typeof value === 'string' ? value : JSON.stringify(value, null, 2);
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
JSON.parse(stringValue);
|
|
25
|
+
setHasError(false);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
setHasError(true);
|
|
28
|
+
}
|
|
29
|
+
}, [value]);
|
|
6
30
|
|
|
7
|
-
export const CustomMetadataField = () => {
|
|
8
31
|
const formatValue = value => {
|
|
9
32
|
if (value === null || value === undefined) {
|
|
10
33
|
return '';
|
|
@@ -15,74 +38,107 @@ export const CustomMetadataField = () => {
|
|
|
15
38
|
return JSON.stringify(value, null, 2);
|
|
16
39
|
};
|
|
17
40
|
|
|
18
|
-
const
|
|
19
|
-
setFieldValue('custom_metadata',
|
|
41
|
+
const updateFormik = val => {
|
|
42
|
+
formik.setFieldValue('custom_metadata', val);
|
|
43
|
+
formik.setFieldTouched('custom_metadata', true);
|
|
44
|
+
|
|
45
|
+
if (!val || val.trim() === '') {
|
|
46
|
+
setHasError(false);
|
|
47
|
+
} else {
|
|
48
|
+
try {
|
|
49
|
+
JSON.parse(val);
|
|
50
|
+
setHasError(false);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
setHasError(true);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
20
55
|
};
|
|
21
56
|
|
|
22
57
|
return (
|
|
23
|
-
<div className="NodeCreationInput"
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
58
|
+
<div className="QueryInput NodeCreationInput">
|
|
59
|
+
<details>
|
|
60
|
+
<summary style={{ cursor: 'pointer' }}>
|
|
61
|
+
<label
|
|
62
|
+
style={{
|
|
63
|
+
paddingLeft: '3px',
|
|
64
|
+
display: 'inline-block',
|
|
65
|
+
pointerEvents: 'none',
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
Custom Metadata (JSON)
|
|
69
|
+
</label>
|
|
70
|
+
</summary>
|
|
71
|
+
<ErrorMessage name="custom_metadata" component="span" />
|
|
72
|
+
<Field
|
|
73
|
+
type="textarea"
|
|
74
|
+
style={{ display: 'none' }}
|
|
75
|
+
as="textarea"
|
|
76
|
+
name="custom_metadata"
|
|
77
|
+
id="CustomMetadata"
|
|
78
|
+
validate={value => {
|
|
79
|
+
if (!value || value.trim() === '') {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const parsed = JSON.parse(value);
|
|
33
84
|
|
|
34
|
-
if (
|
|
35
|
-
typeof parsed === 'object' &&
|
|
36
|
-
parsed !== null &&
|
|
37
|
-
!Array.isArray(parsed)
|
|
38
|
-
) {
|
|
39
|
-
const keys = Object.keys(parsed);
|
|
40
|
-
const originalKeyMatches = value.match(/"([^"]+)"\s*:/g);
|
|
41
85
|
if (
|
|
42
|
-
|
|
43
|
-
|
|
86
|
+
typeof parsed === 'object' &&
|
|
87
|
+
parsed !== null &&
|
|
88
|
+
!Array.isArray(parsed)
|
|
44
89
|
) {
|
|
45
|
-
|
|
90
|
+
const keys = Object.keys(parsed);
|
|
91
|
+
const originalKeyMatches = value.match(/"([^"]+)"\s*:/g);
|
|
92
|
+
if (
|
|
93
|
+
originalKeyMatches &&
|
|
94
|
+
originalKeyMatches.length > keys.length
|
|
95
|
+
) {
|
|
96
|
+
return 'Duplicate keys detected';
|
|
97
|
+
}
|
|
46
98
|
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return undefined;
|
|
50
|
-
} catch (err) {
|
|
51
|
-
return 'Invalid JSON format';
|
|
52
|
-
}
|
|
53
|
-
}}
|
|
54
|
-
>
|
|
55
|
-
{({ field, form }) => {
|
|
56
|
-
const errorMessage = form.errors.custom_metadata;
|
|
57
|
-
const hasError = errorMessage && form.touched.custom_metadata;
|
|
58
99
|
|
|
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
|
-
|
|
100
|
+
return undefined;
|
|
101
|
+
} catch (err) {
|
|
102
|
+
return 'Invalid JSON format';
|
|
103
|
+
}
|
|
104
|
+
}}
|
|
105
|
+
/>
|
|
106
|
+
<div
|
|
107
|
+
role="button"
|
|
108
|
+
tabIndex={0}
|
|
109
|
+
className={`relative flex ${
|
|
110
|
+
hasError ? 'bg-red-900/20' : 'bg-[#282a36]'
|
|
111
|
+
}`}
|
|
112
|
+
style={{
|
|
113
|
+
border: hasError ? '2px solid #ef4444' : 'none',
|
|
114
|
+
borderRadius: '4px',
|
|
115
|
+
boxShadow: hasError ? '0 0 0 1px rgba(239, 68, 68, 0.3)' : 'none',
|
|
116
|
+
}}
|
|
117
|
+
>
|
|
118
|
+
<CodeMirror
|
|
119
|
+
id={'custom_metadata'}
|
|
120
|
+
name={'custom_metadata'}
|
|
121
|
+
extensions={[jsonExt]}
|
|
122
|
+
value={formatValue(value)}
|
|
123
|
+
placeholder={'{\n "key": "value"\n}'}
|
|
124
|
+
options={{
|
|
125
|
+
theme: 'default',
|
|
126
|
+
lineNumbers: true,
|
|
127
|
+
}}
|
|
128
|
+
width="100%"
|
|
129
|
+
height="200px"
|
|
130
|
+
style={{
|
|
131
|
+
margin: '0 0 23px 0',
|
|
132
|
+
flex: 1,
|
|
133
|
+
fontSize: '150%',
|
|
134
|
+
textAlign: 'left',
|
|
135
|
+
}}
|
|
136
|
+
onChange={(value, viewUpdate) => {
|
|
137
|
+
updateFormik(value);
|
|
138
|
+
}}
|
|
139
|
+
/>
|
|
140
|
+
</div>
|
|
141
|
+
</details>
|
|
86
142
|
</div>
|
|
87
143
|
);
|
|
88
144
|
};
|
|
@@ -474,7 +474,6 @@ export function AddEditNodePage({ extensions = {} }) {
|
|
|
474
474
|
) : (
|
|
475
475
|
''
|
|
476
476
|
)}
|
|
477
|
-
<CustomMetadataField />
|
|
478
477
|
{nodeType !== 'metric' && node.type !== 'metric' ? (
|
|
479
478
|
action === Action.Edit ? (
|
|
480
479
|
selectPrimaryKey
|
|
@@ -491,6 +490,11 @@ export function AddEditNodePage({ extensions = {} }) {
|
|
|
491
490
|
) : (
|
|
492
491
|
<RequiredDimensionsSelect />
|
|
493
492
|
)}
|
|
493
|
+
<CustomMetadataField
|
|
494
|
+
value={
|
|
495
|
+
node.custom_metadata ? node.custom_metadata : ''
|
|
496
|
+
}
|
|
497
|
+
/>
|
|
494
498
|
{Object.entries(extensions).map(
|
|
495
499
|
([key, ExtensionComponent]) => (
|
|
496
500
|
<div key={key} className="mt-4 border-t pt-4">
|