@apollo-annotation/jbrowse-plugin-apollo 0.3.4 → 0.3.6

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.
Files changed (131) hide show
  1. package/dist/index.esm.js +5466 -4490
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +5283 -4318
  4. package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
  5. package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
  6. package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
  7. package/dist/jbrowse-plugin-apollo.umd.development.js +6806 -4088
  8. package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
  9. package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
  10. package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
  11. package/package.json +4 -4
  12. package/src/ApolloInternetAccount/addMenuItems.ts +5 -2
  13. package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +1 -0
  14. package/src/ApolloInternetAccount/components/LoginButtons.tsx +1 -1
  15. package/src/ApolloInternetAccount/components/LoginIcons.tsx +1 -1
  16. package/src/ApolloInternetAccount/configSchema.ts +1 -1
  17. package/src/ApolloInternetAccount/model.ts +11 -10
  18. package/src/ApolloJobModel.ts +1 -1
  19. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +8 -6
  20. package/src/ApolloRefNameAliasAdapter/index.ts +2 -2
  21. package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +17 -4
  22. package/src/ApolloSequenceAdapter/index.ts +1 -1
  23. package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +8 -7
  24. package/src/ApolloTextSearchAdapter/index.ts +1 -1
  25. package/src/BackendDrivers/BackendDriver.ts +7 -7
  26. package/src/BackendDrivers/CollaborationServerDriver.ts +14 -10
  27. package/src/BackendDrivers/DesktopFileDriver.ts +11 -10
  28. package/src/BackendDrivers/InMemoryFileDriver.ts +10 -6
  29. package/src/ChangeManager.ts +5 -5
  30. package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +92 -20
  31. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +170 -27
  32. package/src/FeatureDetailsWidget/AttributeKey.tsx +50 -0
  33. package/src/FeatureDetailsWidget/AttributeKeySelector.tsx +104 -0
  34. package/src/FeatureDetailsWidget/Attributes.tsx +213 -320
  35. package/src/FeatureDetailsWidget/BasicInformation.tsx +8 -9
  36. package/src/FeatureDetailsWidget/DefaultAttributeEditor.tsx +104 -0
  37. package/src/FeatureDetailsWidget/DefaultAttributeViewer.tsx +22 -0
  38. package/src/FeatureDetailsWidget/FeatureDetailsNavigation.tsx +10 -8
  39. package/src/FeatureDetailsWidget/NumberTextField.tsx +1 -1
  40. package/src/FeatureDetailsWidget/Sequence.tsx +18 -35
  41. package/src/FeatureDetailsWidget/StringTextField.tsx +1 -1
  42. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +140 -95
  43. package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +600 -0
  44. package/src/FeatureDetailsWidget/TranscriptWidgetSummary.tsx +54 -0
  45. package/src/FeatureDetailsWidget/model.ts +8 -3
  46. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +19 -12
  47. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +19 -41
  48. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +44 -22
  49. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +6 -5
  50. package/src/LinearApolloDisplay/glyphs/Glyph.ts +7 -7
  51. package/src/LinearApolloDisplay/stateModel/base.ts +52 -10
  52. package/src/LinearApolloDisplay/stateModel/index.ts +4 -3
  53. package/src/LinearApolloDisplay/stateModel/layouts.ts +8 -34
  54. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +13 -12
  55. package/src/LinearApolloDisplay/stateModel/rendering.ts +63 -31
  56. package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +221 -0
  57. package/src/LinearApolloSixFrameDisplay/components/TrackLines.tsx +40 -0
  58. package/src/LinearApolloSixFrameDisplay/components/index.ts +2 -0
  59. package/src/LinearApolloSixFrameDisplay/configSchema.ts +7 -0
  60. package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +821 -0
  61. package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +63 -0
  62. package/src/LinearApolloSixFrameDisplay/glyphs/index.ts +1 -0
  63. package/src/LinearApolloSixFrameDisplay/index.ts +2 -0
  64. package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +261 -0
  65. package/src/LinearApolloSixFrameDisplay/stateModel/index.ts +27 -0
  66. package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +236 -0
  67. package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +349 -0
  68. package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +199 -0
  69. package/src/LinearApolloSixFrameDisplay/types.ts +1 -0
  70. package/src/OntologyManager/OntologyStore/fulltext-stopwords.ts +10 -1
  71. package/src/OntologyManager/OntologyStore/fulltext.test.ts +1 -1
  72. package/src/OntologyManager/OntologyStore/fulltext.ts +8 -3
  73. package/src/OntologyManager/OntologyStore/index.test.ts +4 -1
  74. package/src/OntologyManager/OntologyStore/index.ts +19 -14
  75. package/src/OntologyManager/OntologyStore/indexeddb-schema.ts +6 -5
  76. package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +11 -5
  77. package/src/OntologyManager/index.ts +10 -6
  78. package/src/OntologyManager/util.ts +3 -2
  79. package/src/TabularEditor/HybridGrid/ChangeHandling.ts +2 -2
  80. package/src/TabularEditor/HybridGrid/Feature.tsx +9 -8
  81. package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +1 -1
  82. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +3 -2
  83. package/src/TabularEditor/HybridGrid/NumberCell.tsx +8 -1
  84. package/src/TabularEditor/HybridGrid/ToolBar.tsx +15 -13
  85. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +9 -33
  86. package/src/TabularEditor/TabularEditorPane.tsx +1 -1
  87. package/src/TabularEditor/model.ts +2 -2
  88. package/src/TabularEditor/types.ts +5 -2
  89. package/src/components/AddAssembly.tsx +611 -291
  90. package/src/components/AddChildFeature.tsx +6 -5
  91. package/src/components/AddFeature.tsx +211 -38
  92. package/src/components/AddRefSeqAliases.tsx +14 -12
  93. package/src/components/CopyFeature.tsx +8 -7
  94. package/src/components/CreateApolloAnnotation.tsx +154 -46
  95. package/src/components/DeleteAssembly.tsx +9 -8
  96. package/src/components/DeleteFeature.tsx +5 -4
  97. package/src/components/Dialog.tsx +1 -1
  98. package/src/components/DownloadGFF3.tsx +11 -10
  99. package/src/components/FilterFeatures.tsx +6 -4
  100. package/src/components/ImportFeatures.tsx +7 -6
  101. package/src/components/LogOut.tsx +5 -4
  102. package/src/components/ManageChecks.tsx +9 -8
  103. package/src/components/ManageUsers.tsx +11 -10
  104. package/src/components/OntologyTermAutocomplete.tsx +5 -5
  105. package/src/components/OntologyTermMultiSelect.tsx +9 -6
  106. package/src/components/OpenLocalFile.tsx +4 -3
  107. package/src/components/ViewChangeLog.tsx +7 -6
  108. package/src/components/ViewCheckResults.tsx +8 -7
  109. package/src/components/index.ts +0 -1
  110. package/src/extensions/annotationFromJBrowseFeature.test.ts +1 -0
  111. package/src/extensions/annotationFromJBrowseFeature.ts +14 -12
  112. package/src/extensions/annotationFromPileup.ts +6 -6
  113. package/src/index.ts +33 -50
  114. package/src/makeDisplayComponent.tsx +93 -41
  115. package/src/session/ClientDataStore.ts +21 -17
  116. package/src/session/session.ts +20 -26
  117. package/src/types.ts +4 -4
  118. package/src/util/annotationFeatureUtils.ts +53 -0
  119. package/src/util/index.ts +4 -3
  120. package/src/util/loadAssemblyIntoClient.ts +10 -3
  121. package/src/ApolloSixFrameRenderer/ApolloSixFrameRenderer.tsx +0 -13
  122. package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +0 -707
  123. package/src/ApolloSixFrameRenderer/configSchema.ts +0 -7
  124. package/src/ApolloSixFrameRenderer/index.ts +0 -3
  125. package/src/FeatureDetailsWidget/TranscriptBasic.tsx +0 -200
  126. package/src/SixFrameFeatureDisplay/components/TrackLines.tsx +0 -19
  127. package/src/SixFrameFeatureDisplay/components/index.ts +0 -1
  128. package/src/SixFrameFeatureDisplay/configSchema.ts +0 -21
  129. package/src/SixFrameFeatureDisplay/index.ts +0 -2
  130. package/src/SixFrameFeatureDisplay/stateModel.ts +0 -439
  131. package/src/components/ModifyFeatureAttribute.tsx +0 -460
@@ -1,16 +1,38 @@
1
- import { AbstractSessionModel, getSession } from '@jbrowse/core/util'
1
+ import { type AnnotationFeature } from '@apollo-annotation/mst'
2
+ import styled from '@emotion/styled'
3
+ import {
4
+ type AbstractSessionModel,
5
+ getEnv,
6
+ getSession,
7
+ } from '@jbrowse/core/util'
8
+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
9
+ import InfoIcon from '@mui/icons-material/Info'
10
+ import {
11
+ Accordion,
12
+ AccordionDetails,
13
+ AccordionSummary,
14
+ Tooltip,
15
+ Typography,
16
+ } from '@mui/material'
2
17
  import { observer } from 'mobx-react'
3
18
  import { getRoot } from 'mobx-state-tree'
4
- import React from 'react'
19
+ import React, { useEffect, useState } from 'react'
5
20
  import { makeStyles } from 'tss-react/mui'
6
21
 
7
- import { ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
8
- import { ApolloSessionModel } from '../session'
9
- import { ApolloRootModel } from '../types'
22
+ import { type ApolloInternetAccountModel } from '../ApolloInternetAccount/model'
23
+ import { type ApolloSessionModel } from '../session'
24
+ import { type ApolloRootModel } from '../types'
25
+
10
26
  import { Attributes } from './Attributes'
11
- import { TranscriptBasicInformation } from './TranscriptBasic'
12
27
  import { TranscriptSequence } from './TranscriptSequence'
13
- import { ApolloTranscriptDetailsWidget as ApolloTranscriptDetailsWidgetState } from './model'
28
+ import { TranscriptWidgetEditLocation } from './TranscriptWidgetEditLocation'
29
+ import { TranscriptWidgetSummary } from './TranscriptWidgetSummary'
30
+ import { type ApolloTranscriptDetailsWidget as ApolloTranscriptDetailsWidgetState } from './model'
31
+
32
+ interface CustomComponentProps {
33
+ session: AbstractSessionModel
34
+ feature: AnnotationFeature
35
+ }
14
36
 
15
37
  const useStyles = makeStyles()((theme) => ({
16
38
  root: {
@@ -18,14 +40,37 @@ const useStyles = makeStyles()((theme) => ({
18
40
  },
19
41
  }))
20
42
 
43
+ export const StyledAccordionSummary = styled(AccordionSummary)(() => ({
44
+ minHeight: 30,
45
+ maxHeight: 30,
46
+ '&.Mui-expanded': {
47
+ minHeight: 30,
48
+ maxHeight: 30,
49
+ },
50
+ }))
51
+
52
+ function NoOpCustomComponent(_props: CustomComponentProps) {
53
+ return null
54
+ }
55
+
21
56
  export const ApolloTranscriptDetailsWidget = observer(
22
57
  function ApolloTranscriptDetails(props: {
23
58
  model: ApolloTranscriptDetailsWidgetState
24
59
  }) {
25
60
  const { classes } = useStyles()
61
+ const DEFAULT_PANELS = ['summary', 'location', 'attrs']
62
+ const [panelState, setPanelState] = useState<string[]>(DEFAULT_PANELS)
63
+
26
64
  const { model } = props
27
65
  const { assembly, feature, refName } = model
66
+
67
+ useEffect(() => {
68
+ setPanelState(DEFAULT_PANELS)
69
+ // eslint-disable-next-line react-hooks/exhaustive-deps
70
+ }, [feature])
71
+
28
72
  const session = getSession(model) as unknown as AbstractSessionModel
73
+ const { pluginManager } = getEnv(session)
29
74
  const apolloSession = getSession(model) as unknown as ApolloSessionModel
30
75
  const currentAssembly =
31
76
  apolloSession.apolloDataStore.assemblies.get(assembly)
@@ -53,28 +98,126 @@ export const ApolloTranscriptDetailsWidget = observer(
53
98
  ])
54
99
  }
55
100
 
101
+ function handlePanelChange(expanded: boolean, panel: string) {
102
+ if (expanded) {
103
+ setPanelState([...panelState, panel])
104
+ } else {
105
+ setPanelState(panelState.filter((p) => p !== panel))
106
+ }
107
+ }
108
+
109
+ const CustomComponent = pluginManager.evaluateExtensionPoint(
110
+ 'Apollo-TranscriptDetailsCustomComponent',
111
+ NoOpCustomComponent,
112
+ props,
113
+ ) as React.ElementType<CustomComponentProps>
114
+
56
115
  return (
57
116
  <div className={classes.root}>
58
- <TranscriptBasicInformation
59
- feature={feature}
60
- session={apolloSession}
61
- assembly={currentAssembly._id || ''}
62
- refName={refName}
63
- />
64
- <hr />
65
- <Attributes
66
- feature={feature}
67
- session={apolloSession}
68
- assembly={currentAssembly._id || ''}
69
- editable={editable}
70
- />
71
- <hr />
72
- <TranscriptSequence
73
- feature={feature}
74
- session={apolloSession}
75
- assembly={currentAssembly._id || ''}
76
- refName={refName}
77
- />
117
+ <Accordion
118
+ expanded={panelState.includes('summary')}
119
+ onChange={(e, expanded) => {
120
+ handlePanelChange(expanded, 'summary')
121
+ }}
122
+ >
123
+ <StyledAccordionSummary
124
+ expandIcon={<ExpandMoreIcon style={{ color: 'white' }} />}
125
+ aria-controls="panel1-content"
126
+ id="panel1-header"
127
+ >
128
+ <Typography component="span" fontWeight={'bold'}>
129
+ Summary
130
+ </Typography>
131
+ </StyledAccordionSummary>
132
+ <AccordionDetails>
133
+ <TranscriptWidgetSummary feature={feature} refName={refName} />
134
+ </AccordionDetails>
135
+ </Accordion>
136
+ <CustomComponent session={session} feature={feature} />
137
+ <Accordion
138
+ style={{ marginTop: 5 }}
139
+ expanded={panelState.includes('location')}
140
+ onChange={(e, expanded) => {
141
+ handlePanelChange(expanded, 'location')
142
+ }}
143
+ >
144
+ <StyledAccordionSummary
145
+ expandIcon={<ExpandMoreIcon style={{ color: 'white' }} />}
146
+ aria-controls="panel2-content"
147
+ id="panel2-header"
148
+ >
149
+ <Typography component="span" fontWeight={'bold'}>
150
+ Location
151
+ </Typography>
152
+ </StyledAccordionSummary>
153
+ <AccordionDetails>
154
+ <TranscriptWidgetEditLocation
155
+ feature={feature}
156
+ refName={refName}
157
+ session={apolloSession}
158
+ assembly={currentAssembly._id || ''}
159
+ />
160
+ </AccordionDetails>
161
+ </Accordion>
162
+ <Accordion
163
+ style={{ marginTop: 5 }}
164
+ expanded={panelState.includes('attrs')}
165
+ onChange={(e, expanded) => {
166
+ handlePanelChange(expanded, 'attrs')
167
+ }}
168
+ >
169
+ <StyledAccordionSummary
170
+ expandIcon={<ExpandMoreIcon style={{ color: 'white' }} />}
171
+ aria-controls="panel3-content"
172
+ id="panel3-header"
173
+ >
174
+ <div style={{ display: 'flex', alignItems: 'center' }}>
175
+ <Typography component="span" fontWeight={'bold'}>
176
+ Attributes{' '}
177
+ </Typography>
178
+ <Tooltip title="Separate multiple values for the attribute with commas">
179
+ <InfoIcon
180
+ style={{ color: 'white', fontSize: 15, marginLeft: 10 }}
181
+ />
182
+ </Tooltip>
183
+ </div>
184
+ </StyledAccordionSummary>
185
+ <AccordionDetails>
186
+ <Attributes
187
+ feature={feature}
188
+ session={apolloSession}
189
+ assembly={currentAssembly._id || ''}
190
+ editable={editable}
191
+ />
192
+ </AccordionDetails>
193
+ </Accordion>
194
+ <Accordion
195
+ style={{ marginTop: 5 }}
196
+ expanded={panelState.includes('sequence')}
197
+ onChange={(e, expanded) => {
198
+ handlePanelChange(expanded, 'sequence')
199
+ }}
200
+ >
201
+ <StyledAccordionSummary
202
+ expandIcon={<ExpandMoreIcon style={{ color: 'white' }} />}
203
+ aria-controls="panel4-content"
204
+ id="panel4-header"
205
+ >
206
+ <Typography component="span" fontWeight={'bold'}>
207
+ Sequence
208
+ </Typography>
209
+ </StyledAccordionSummary>
210
+ <AccordionDetails>
211
+ {panelState.includes('sequence') && (
212
+ <TranscriptSequence
213
+ feature={feature}
214
+ session={apolloSession}
215
+ assembly={currentAssembly._id || ''}
216
+ refName={refName}
217
+ />
218
+ )}
219
+ </AccordionDetails>
220
+ </Accordion>
78
221
  </div>
79
222
  )
80
223
  },
@@ -0,0 +1,50 @@
1
+ import {
2
+ gffInternalToColumn,
3
+ internalToGFF,
4
+ isGFFColumnInternal,
5
+ isGFFInternalAttribute,
6
+ } from '@apollo-annotation/shared'
7
+ import InfoIcon from '@mui/icons-material/Info'
8
+ import { Chip, Tooltip, Typography } from '@mui/material'
9
+ import React from 'react'
10
+ import { makeStyles } from 'tss-react/mui'
11
+
12
+ const useStyles = makeStyles()((theme) => ({
13
+ attributeKey: {
14
+ fontWeight: 'bold',
15
+ marginRight: theme.spacing(2),
16
+ },
17
+ }))
18
+
19
+ export function AttributeKey({ attributeKey: key }: { attributeKey: string }) {
20
+ const { classes } = useStyles()
21
+
22
+ const startsWithCapital = /^[A-Z]/.test(key)
23
+ let displayKey = key
24
+ let titleText: string | undefined
25
+ if (isGFFInternalAttribute(key)) {
26
+ displayKey = internalToGFF[key]
27
+ titleText = `On GFF3 export, this will be assigned to the GFF3's reserved "${displayKey}" attribute`
28
+ } else if (isGFFColumnInternal(key)) {
29
+ displayKey = gffInternalToColumn[key]
30
+ titleText = `On GFF3 export, this will be placed in the GFF3's "${displayKey}" column`
31
+ } else if (startsWithCapital) {
32
+ titleText =
33
+ 'On GFF3 export, this attribute will be changed to start with a lower-case letter because attributes starting with an upper-case letter are reserved in GFF3'
34
+ }
35
+ return (
36
+ <div style={{ display: 'flex' }}>
37
+ <Typography className={classes.attributeKey}>{displayKey}</Typography>
38
+ {titleText ? (
39
+ <Tooltip title={titleText}>
40
+ <Chip
41
+ icon={<InfoIcon />}
42
+ label="GFF3"
43
+ size="small"
44
+ variant="outlined"
45
+ />
46
+ </Tooltip>
47
+ ) : null}
48
+ </div>
49
+ )
50
+ }
@@ -0,0 +1,104 @@
1
+ import { gffColumnToInternal, gffToInternal } from '@apollo-annotation/shared'
2
+ import { getEnv } from '@jbrowse/core/util'
3
+ import {
4
+ Button,
5
+ DialogActions,
6
+ FormControl,
7
+ InputLabel,
8
+ MenuItem,
9
+ Select,
10
+ TextField,
11
+ } from '@mui/material'
12
+ import { observer } from 'mobx-react'
13
+ import React, { useState } from 'react'
14
+
15
+ import { type ApolloSessionModel } from '../session'
16
+
17
+ const customKeyName = 'Custom'
18
+ const gffKeys: Record<string, string | undefined> = {
19
+ [customKeyName]: 'custom',
20
+ }
21
+
22
+ for (const [value, key] of Object.entries(gffToInternal)) {
23
+ gffKeys[`GFF ${key}`] = value
24
+ }
25
+ for (const [value, key] of Object.entries(gffColumnToInternal)) {
26
+ gffKeys[`GFF ${key}`] = value
27
+ }
28
+
29
+ export const AttributeKeySelector = observer(function AttributeKeySelector({
30
+ setKey,
31
+ session,
32
+ }: {
33
+ setKey: (newKey?: string) => void
34
+ session: ApolloSessionModel
35
+ }) {
36
+ const { pluginManager } = getEnv(session)
37
+ const reservedKeys = pluginManager.evaluateExtensionPoint(
38
+ 'Apollo-ReservedAttributeKeys',
39
+ gffKeys,
40
+ ) as Record<string, string | undefined>
41
+ const firstKey = Object.keys(reservedKeys).at(0) ?? customKeyName
42
+ const [selectedKey, setSelectedKey] = useState<string>(firstKey)
43
+ const [customKey, setCustomKey] = useState<string>()
44
+ const isCustom = selectedKey === customKeyName
45
+
46
+ function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
47
+ event.preventDefault()
48
+ if (isCustom) {
49
+ setKey(customKey)
50
+ return
51
+ }
52
+ setKey(reservedKeys[selectedKey])
53
+ }
54
+ function handleCancel() {
55
+ setKey()
56
+ }
57
+
58
+ return (
59
+ <form onSubmit={handleSubmit}>
60
+ <div style={{ display: 'flex', flexDirection: 'column', margin: 8 }}>
61
+ <FormControl variant="outlined">
62
+ <InputLabel id="attribute-key-select-label">Key</InputLabel>
63
+ <Select
64
+ labelId="attribute-key-select-label"
65
+ value={selectedKey}
66
+ label="Key"
67
+ onChange={(event) => {
68
+ setSelectedKey(event.target.value)
69
+ }}
70
+ >
71
+ {Object.keys(reservedKeys).map((val) => (
72
+ <MenuItem key={val} value={val}>
73
+ {val}
74
+ </MenuItem>
75
+ ))}
76
+ </Select>
77
+ </FormControl>
78
+ {isCustom ? (
79
+ <TextField
80
+ label="Attribute key"
81
+ variant="outlined"
82
+ id="attributeKey"
83
+ onChange={(event) => {
84
+ setCustomKey(event.target.value)
85
+ }}
86
+ />
87
+ ) : null}
88
+ </div>
89
+ <DialogActions>
90
+ <Button
91
+ color="primary"
92
+ variant="contained"
93
+ type="submit"
94
+ disabled={isCustom && !customKey}
95
+ >
96
+ Add
97
+ </Button>
98
+ <Button variant="outlined" onClick={handleCancel}>
99
+ Cancel
100
+ </Button>
101
+ </DialogActions>
102
+ </form>
103
+ )
104
+ })