@jbrowse/plugin-config 1.7.7 → 1.7.10
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/dist/ConfigurationEditorWidget/components/CodeEditor.js +16 -13
- package/dist/ConfigurationEditorWidget/components/SlotEditor.js +72 -110
- package/dist/ConfigurationEditorWidget/components/StringArrayEditor.d.ts +12 -0
- package/dist/ConfigurationEditorWidget/components/StringArrayEditor.js +110 -0
- package/dist/ConfigurationEditorWidget/index.js +2 -2
- package/package.json +2 -2
- package/src/ConfigurationEditorWidget/components/CodeEditor.js +4 -3
- package/src/ConfigurationEditorWidget/components/SlotEditor.js +28 -73
- package/src/ConfigurationEditorWidget/components/StringArrayEditor.tsx +115 -0
- package/src/ConfigurationEditorWidget/components/__snapshots__/ConfigurationEditor.test.js.snap +110 -142
- package/src/ConfigurationEditorWidget/index.js +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react'
|
|
2
2
|
import { observer } from 'mobx-react'
|
|
3
3
|
import { getPropertyMembers, getEnv } from 'mobx-state-tree'
|
|
4
|
-
import { FileSelector } from '@jbrowse/core/ui'
|
|
4
|
+
import { FileSelector, SanitizedHTML } from '@jbrowse/core/ui'
|
|
5
5
|
import {
|
|
6
6
|
getPropertyType,
|
|
7
7
|
getSubType,
|
|
@@ -18,8 +18,6 @@ import {
|
|
|
18
18
|
IconButton,
|
|
19
19
|
InputAdornment,
|
|
20
20
|
InputLabel,
|
|
21
|
-
List,
|
|
22
|
-
ListItem,
|
|
23
21
|
MenuItem,
|
|
24
22
|
Paper,
|
|
25
23
|
SvgIcon,
|
|
@@ -33,16 +31,32 @@ import AddIcon from '@material-ui/icons/Add'
|
|
|
33
31
|
import RadioButtonUncheckedIcon from '@material-ui/icons/RadioButtonUnchecked'
|
|
34
32
|
|
|
35
33
|
// locals
|
|
34
|
+
import StringArrayEditor from './StringArrayEditor'
|
|
36
35
|
import CallbackEditor from './CallbackEditor'
|
|
37
36
|
import ColorEditor from './ColorEditor'
|
|
38
37
|
import JsonEditor from './JsonEditor'
|
|
39
38
|
|
|
39
|
+
// adds ability to have html in helperText. note that FormHelperTextProps is
|
|
40
|
+
// div because the default is p which does not like div children
|
|
41
|
+
const MyTextField = props => {
|
|
42
|
+
// eslint-disable-next-line react/prop-types
|
|
43
|
+
const { helperText } = props
|
|
44
|
+
return (
|
|
45
|
+
<TextField
|
|
46
|
+
{...props}
|
|
47
|
+
helperText={<SanitizedHTML html={helperText} />}
|
|
48
|
+
FormHelperTextProps={{
|
|
49
|
+
component: 'div',
|
|
50
|
+
}}
|
|
51
|
+
fullWidth
|
|
52
|
+
/>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
40
56
|
const StringEditor = observer(({ slot }) => (
|
|
41
|
-
<
|
|
57
|
+
<MyTextField
|
|
42
58
|
label={slot.name}
|
|
43
|
-
// error={filterError}
|
|
44
59
|
helperText={slot.description}
|
|
45
|
-
fullWidth
|
|
46
60
|
value={slot.value}
|
|
47
61
|
onChange={evt => slot.set(evt.target.value)}
|
|
48
62
|
/>
|
|
@@ -52,7 +66,6 @@ const TextEditor = observer(({ slot }) => (
|
|
|
52
66
|
<TextField
|
|
53
67
|
label={slot.name}
|
|
54
68
|
helperText={slot.description}
|
|
55
|
-
fullWidth
|
|
56
69
|
multiline
|
|
57
70
|
value={slot.value}
|
|
58
71
|
onChange={evt => slot.set(evt.target.value)}
|
|
@@ -66,62 +79,6 @@ const SvgCheckbox = () => (
|
|
|
66
79
|
</SvgIcon>
|
|
67
80
|
)
|
|
68
81
|
|
|
69
|
-
const StringArrayEditor = observer(({ slot }) => {
|
|
70
|
-
const [value, setValue] = useState('')
|
|
71
|
-
return (
|
|
72
|
-
<>
|
|
73
|
-
{slot.name ? <InputLabel>{slot.name}</InputLabel> : null}
|
|
74
|
-
<List disablePadding>
|
|
75
|
-
{slot.value.map((val, idx) => (
|
|
76
|
-
<ListItem key={idx} disableGutters>
|
|
77
|
-
<TextField
|
|
78
|
-
value={val}
|
|
79
|
-
onChange={evt => slot.setAtIndex(idx, evt.target.value)}
|
|
80
|
-
InputProps={{
|
|
81
|
-
endAdornment: (
|
|
82
|
-
<InputAdornment position="end">
|
|
83
|
-
<IconButton
|
|
84
|
-
color="secondary"
|
|
85
|
-
onClick={() => slot.removeAtIndex(idx)}
|
|
86
|
-
>
|
|
87
|
-
<DeleteIcon />
|
|
88
|
-
</IconButton>
|
|
89
|
-
</InputAdornment>
|
|
90
|
-
),
|
|
91
|
-
}}
|
|
92
|
-
/>
|
|
93
|
-
</ListItem>
|
|
94
|
-
))}
|
|
95
|
-
<ListItem disableGutters>
|
|
96
|
-
<TextField
|
|
97
|
-
value={value}
|
|
98
|
-
placeholder="add new"
|
|
99
|
-
onChange={event => setValue(event.target.value)}
|
|
100
|
-
InputProps={{
|
|
101
|
-
endAdornment: (
|
|
102
|
-
<InputAdornment position="end">
|
|
103
|
-
<IconButton
|
|
104
|
-
onClick={() => {
|
|
105
|
-
slot.add(value)
|
|
106
|
-
setValue('')
|
|
107
|
-
}}
|
|
108
|
-
disabled={value === ''}
|
|
109
|
-
color="secondary"
|
|
110
|
-
data-testid={`stringArrayAdd-${slot.name}`}
|
|
111
|
-
>
|
|
112
|
-
<AddIcon />
|
|
113
|
-
</IconButton>
|
|
114
|
-
</InputAdornment>
|
|
115
|
-
),
|
|
116
|
-
}}
|
|
117
|
-
/>
|
|
118
|
-
</ListItem>
|
|
119
|
-
</List>
|
|
120
|
-
<FormHelperText>{slot.description}</FormHelperText>
|
|
121
|
-
</>
|
|
122
|
-
)
|
|
123
|
-
})
|
|
124
|
-
|
|
125
82
|
const useMapEditorStyles = makeStyles(theme => ({
|
|
126
83
|
card: {
|
|
127
84
|
marginTop: theme.spacing(1),
|
|
@@ -268,7 +225,7 @@ const NumberEditor = observer(({ slot }) => {
|
|
|
268
225
|
}
|
|
269
226
|
}, [slot, val])
|
|
270
227
|
return (
|
|
271
|
-
<
|
|
228
|
+
<MyTextField
|
|
272
229
|
label={slot.name}
|
|
273
230
|
helperText={slot.description}
|
|
274
231
|
value={val}
|
|
@@ -287,7 +244,7 @@ const IntegerEditor = observer(({ slot }) => {
|
|
|
287
244
|
}
|
|
288
245
|
}, [slot, val])
|
|
289
246
|
return (
|
|
290
|
-
<
|
|
247
|
+
<MyTextField
|
|
291
248
|
label={slot.name}
|
|
292
249
|
helperText={slot.description}
|
|
293
250
|
value={val}
|
|
@@ -297,7 +254,7 @@ const IntegerEditor = observer(({ slot }) => {
|
|
|
297
254
|
)
|
|
298
255
|
})
|
|
299
256
|
|
|
300
|
-
const
|
|
257
|
+
const BooleanEditor = observer(({ slot }) => (
|
|
301
258
|
<FormControl>
|
|
302
259
|
<FormControlLabel
|
|
303
260
|
label={slot.name}
|
|
@@ -312,20 +269,18 @@ const booleanEditor = observer(({ slot }) => (
|
|
|
312
269
|
</FormControl>
|
|
313
270
|
))
|
|
314
271
|
|
|
315
|
-
const
|
|
272
|
+
const StringEnumEditor = observer(({ slot, slotSchema }) => {
|
|
316
273
|
const p = getPropertyMembers(getSubType(slotSchema))
|
|
317
274
|
const choices = getUnionSubTypes(
|
|
318
275
|
getUnionSubTypes(getSubType(getPropertyType(p, 'value')))[1],
|
|
319
276
|
).map(t => t.value)
|
|
320
277
|
|
|
321
278
|
return (
|
|
322
|
-
<
|
|
279
|
+
<MyTextField
|
|
323
280
|
value={slot.value}
|
|
324
281
|
label={slot.name}
|
|
325
282
|
select
|
|
326
|
-
// error={filterError}
|
|
327
283
|
helperText={slot.description}
|
|
328
|
-
fullWidth
|
|
329
284
|
onChange={evt => slot.set(evt.target.value)}
|
|
330
285
|
>
|
|
331
286
|
{choices.map(str => (
|
|
@@ -333,7 +288,7 @@ const stringEnumEditor = observer(({ slot, slotSchema }) => {
|
|
|
333
288
|
{str}
|
|
334
289
|
</MenuItem>
|
|
335
290
|
))}
|
|
336
|
-
</
|
|
291
|
+
</MyTextField>
|
|
337
292
|
)
|
|
338
293
|
})
|
|
339
294
|
|
|
@@ -359,8 +314,8 @@ const valueComponents = {
|
|
|
359
314
|
number: NumberEditor,
|
|
360
315
|
integer: IntegerEditor,
|
|
361
316
|
color: ColorEditor,
|
|
362
|
-
stringEnum:
|
|
363
|
-
boolean:
|
|
317
|
+
stringEnum: StringEnumEditor,
|
|
318
|
+
boolean: BooleanEditor,
|
|
364
319
|
frozen: JsonEditor,
|
|
365
320
|
configRelationships: JsonEditor,
|
|
366
321
|
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { observer } from 'mobx-react'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
FormHelperText,
|
|
7
|
+
IconButton,
|
|
8
|
+
InputAdornment,
|
|
9
|
+
InputLabel,
|
|
10
|
+
List,
|
|
11
|
+
ListItem,
|
|
12
|
+
TextField,
|
|
13
|
+
} from '@material-ui/core'
|
|
14
|
+
|
|
15
|
+
// icons
|
|
16
|
+
import DeleteIcon from '@material-ui/icons/Delete'
|
|
17
|
+
|
|
18
|
+
const StringArrayEditor = observer(
|
|
19
|
+
({
|
|
20
|
+
slot,
|
|
21
|
+
}: {
|
|
22
|
+
slot: {
|
|
23
|
+
name: string
|
|
24
|
+
value: string[]
|
|
25
|
+
setAtIndex: Function
|
|
26
|
+
removeAtIndex: Function
|
|
27
|
+
add: Function
|
|
28
|
+
description: string
|
|
29
|
+
}
|
|
30
|
+
}) => {
|
|
31
|
+
const [value, setValue] = useState('')
|
|
32
|
+
const [addNew, setAddNew] = useState(false)
|
|
33
|
+
return (
|
|
34
|
+
<>
|
|
35
|
+
{slot.name ? <InputLabel>{slot.name}</InputLabel> : null}
|
|
36
|
+
<List disablePadding>
|
|
37
|
+
{slot.value.map((val, idx) => (
|
|
38
|
+
<ListItem key={idx} disableGutters>
|
|
39
|
+
<TextField
|
|
40
|
+
value={val}
|
|
41
|
+
onChange={evt => slot.setAtIndex(idx, evt.target.value)}
|
|
42
|
+
InputProps={{
|
|
43
|
+
endAdornment: (
|
|
44
|
+
<InputAdornment position="end">
|
|
45
|
+
<IconButton
|
|
46
|
+
color="secondary"
|
|
47
|
+
onClick={() => slot.removeAtIndex(idx)}
|
|
48
|
+
>
|
|
49
|
+
<DeleteIcon />
|
|
50
|
+
</IconButton>
|
|
51
|
+
</InputAdornment>
|
|
52
|
+
),
|
|
53
|
+
}}
|
|
54
|
+
/>
|
|
55
|
+
</ListItem>
|
|
56
|
+
))}
|
|
57
|
+
|
|
58
|
+
{addNew ? (
|
|
59
|
+
<ListItem disableGutters>
|
|
60
|
+
<TextField
|
|
61
|
+
value={value}
|
|
62
|
+
placeholder="add new"
|
|
63
|
+
onChange={event => setValue(event.target.value)}
|
|
64
|
+
InputProps={{
|
|
65
|
+
endAdornment: (
|
|
66
|
+
<InputAdornment position="end">
|
|
67
|
+
<>
|
|
68
|
+
<Button
|
|
69
|
+
color="primary"
|
|
70
|
+
variant="contained"
|
|
71
|
+
style={{ margin: 2 }}
|
|
72
|
+
data-testid={`stringArrayAdd-${slot.name}`}
|
|
73
|
+
onClick={() => {
|
|
74
|
+
setAddNew(false)
|
|
75
|
+
slot.add(value)
|
|
76
|
+
setValue('')
|
|
77
|
+
}}
|
|
78
|
+
>
|
|
79
|
+
OK
|
|
80
|
+
</Button>
|
|
81
|
+
<Button
|
|
82
|
+
color="primary"
|
|
83
|
+
variant="contained"
|
|
84
|
+
style={{ margin: 2 }}
|
|
85
|
+
onClick={() => {
|
|
86
|
+
setAddNew(false)
|
|
87
|
+
setValue('')
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
Cancel
|
|
91
|
+
</Button>
|
|
92
|
+
</>
|
|
93
|
+
</InputAdornment>
|
|
94
|
+
),
|
|
95
|
+
}}
|
|
96
|
+
/>
|
|
97
|
+
</ListItem>
|
|
98
|
+
) : null}
|
|
99
|
+
<Button
|
|
100
|
+
color="primary"
|
|
101
|
+
variant="contained"
|
|
102
|
+
style={{ margin: 4 }}
|
|
103
|
+
disabled={addNew}
|
|
104
|
+
onClick={() => setAddNew(true)}
|
|
105
|
+
>
|
|
106
|
+
Add item
|
|
107
|
+
</Button>
|
|
108
|
+
</List>
|
|
109
|
+
<FormHelperText>{slot.description}</FormHelperText>
|
|
110
|
+
</>
|
|
111
|
+
)
|
|
112
|
+
},
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
export default StringArrayEditor
|