@jbrowse/plugin-data-management 1.7.8 → 1.7.11

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 (28) hide show
  1. package/dist/AddConnectionWidget/components/AddConnectionWidget.test.js +25 -16
  2. package/dist/AddConnectionWidget/model.d.ts +1 -1
  3. package/dist/AddTrackWidget/index.test.js +1 -0
  4. package/dist/AddTrackWidget/model.js +1 -1
  5. package/dist/HierarchicalTrackSelectorWidget/components/CloseConnectionDialog.d.ts +7 -1
  6. package/dist/HierarchicalTrackSelectorWidget/components/CloseConnectionDialog.js +2 -5
  7. package/dist/HierarchicalTrackSelectorWidget/components/DeleteConnectionDialog.d.ts +1 -1
  8. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.d.ts +9 -5
  9. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js +67 -51
  10. package/dist/HierarchicalTrackSelectorWidget/components/ManageConnectionsDialog.d.ts +2 -1
  11. package/dist/HierarchicalTrackSelectorWidget/components/ToggleConnectionsDialog.d.ts +2 -1
  12. package/dist/HierarchicalTrackSelectorWidget/components/ToggleConnectionsDialog.js +10 -11
  13. package/dist/HierarchicalTrackSelectorWidget/index.d.ts +2 -2
  14. package/dist/HierarchicalTrackSelectorWidget/model.d.ts +38 -16
  15. package/dist/HierarchicalTrackSelectorWidget/model.js +89 -97
  16. package/dist/ucsc-trackhub/configSchema.d.ts +1 -1
  17. package/dist/ucsc-trackhub/ucscAssemblies.d.ts +1 -1
  18. package/package.json +2 -2
  19. package/src/AddConnectionWidget/components/AddConnectionWidget.test.js +2 -1
  20. package/src/AddTrackWidget/index.test.jsx +1 -0
  21. package/src/AddTrackWidget/model.ts +1 -1
  22. package/src/HierarchicalTrackSelectorWidget/components/CloseConnectionDialog.tsx +7 -11
  23. package/src/HierarchicalTrackSelectorWidget/components/DeleteConnectionDialog.tsx +1 -1
  24. package/src/HierarchicalTrackSelectorWidget/components/{HierarchicalTrackSelector.js → HierarchicalTrackSelector.tsx} +247 -135
  25. package/src/HierarchicalTrackSelectorWidget/components/ManageConnectionsDialog.tsx +5 -2
  26. package/src/HierarchicalTrackSelectorWidget/components/ToggleConnectionsDialog.tsx +24 -26
  27. package/src/HierarchicalTrackSelectorWidget/{index.js → index.ts} +0 -0
  28. package/src/HierarchicalTrackSelectorWidget/{model.js → model.ts} +113 -105
@@ -1,4 +1,3 @@
1
- /* eslint-disable react/prop-types */
2
1
  import React, {
3
2
  Suspense,
4
3
  lazy,
@@ -34,11 +33,23 @@ import { Cable } from '@jbrowse/core/ui/Icons'
34
33
  // other
35
34
  import AutoSizer from 'react-virtualized-auto-sizer'
36
35
  import JBrowseMenu from '@jbrowse/core/ui/Menu'
37
- import { getSession } from '@jbrowse/core/util'
38
- import { readConfObject } from '@jbrowse/core/configuration'
36
+ import {
37
+ getSession,
38
+ isSessionModelWithWidgets,
39
+ isSessionModelWithConnections,
40
+ isSessionWithAddTracks,
41
+ } from '@jbrowse/core/util'
42
+ import {
43
+ AnyConfigurationModel,
44
+ readConfObject,
45
+ } from '@jbrowse/core/configuration'
39
46
  import { observer } from 'mobx-react'
40
47
  import { VariableSizeTree } from 'react-vtree'
41
48
 
49
+ // locals
50
+ import { TreeNode, HierarchicalTrackSelectorModel } from '../model'
51
+
52
+ // lazy components
42
53
  const CloseConnectionDialog = lazy(() => import('./CloseConnectionDialog'))
43
54
  const DeleteConnectionDialog = lazy(() => import('./DeleteConnectionDialog'))
44
55
  const ManageConnectionsDialog = lazy(() => import('./ManageConnectionsDialog'))
@@ -101,9 +112,31 @@ const useStyles = makeStyles(theme => ({
101
112
  },
102
113
  }))
103
114
 
115
+ interface MoreInfoArgs {
116
+ target: HTMLElement
117
+ id: string
118
+ conf: AnyConfigurationModel
119
+ }
120
+
104
121
  // An individual node in the track selector. Note: manually sets cursor:
105
122
  // pointer improves usability for what can be clicked
106
- const Node = props => {
123
+ function Node(props: {
124
+ data: {
125
+ isLeaf: boolean
126
+ nestingLevel: number
127
+ checked: boolean
128
+ id: string
129
+ name: string
130
+ onChange: Function
131
+ toggleCollapse: (arg: string) => void
132
+ conf: AnyConfigurationModel
133
+ onMoreInfo: (arg: MoreInfoArgs) => void
134
+ drawerPosition: unknown
135
+ }
136
+ isOpen: boolean
137
+ style?: { height: number }
138
+ setOpen: (arg: boolean) => void
139
+ }) {
107
140
  const { data, isOpen, style, setOpen } = props
108
141
  const {
109
142
  isLeaf,
@@ -122,7 +155,7 @@ const Node = props => {
122
155
  const width = 10
123
156
  const marginLeft = nestingLevel * width + (isLeaf ? width : 0)
124
157
  const unsupported =
125
- name && (name.endsWith('(Unsupported)') || name.endsWith('(Unknown)'))
158
+ name?.endsWith('(Unsupported)') || name?.endsWith('(Unknown)')
126
159
  const description = (conf && readConfObject(conf, ['description'])) || ''
127
160
 
128
161
  return (
@@ -130,7 +163,7 @@ const Node = props => {
130
163
  {new Array(nestingLevel).fill(0).map((_, idx) => (
131
164
  <div
132
165
  key={`mark-${idx}`}
133
- style={{ left: idx * width + 4, height: style.height }}
166
+ style={{ left: idx * width + 4, height: style?.height }}
134
167
  className={classes.nestingLevelMarker}
135
168
  />
136
169
  ))}
@@ -170,6 +203,7 @@ const Node = props => {
170
203
  color="primary"
171
204
  disabled={unsupported}
172
205
  inputProps={{
206
+ // @ts-ignore
173
207
  'data-testid': `htsTrackEntry-${id}`,
174
208
  }}
175
209
  />
@@ -192,7 +226,11 @@ const Node = props => {
192
226
  )
193
227
  }
194
228
 
195
- const getNodeData = (node, nestingLevel, extra) => {
229
+ function getNodeData(
230
+ node: TreeNode,
231
+ nestingLevel: number,
232
+ extra: Record<string, unknown>,
233
+ ) {
196
234
  const isLeaf = !!node.conf
197
235
  return {
198
236
  data: {
@@ -208,74 +246,99 @@ const getNodeData = (node, nestingLevel, extra) => {
208
246
  }
209
247
  }
210
248
 
249
+ type NodeData = ReturnType<typeof getNodeData>
250
+
211
251
  // this is the main tree component for the hierarchical track selector in note:
212
252
  // in jbrowse-web the toolbar is position="sticky" which means the autosizer
213
253
  // includes the height of the toolbar, so we subtract the given offsets
214
- const HierarchicalTree = observer(({ height, tree, model }) => {
215
- const { filterText, view } = model
216
- const treeRef = useRef(null)
217
- const [info, setMoreInfo] = useState()
218
- const session = getSession(model)
219
- const { drawerPosition } = session
220
-
221
- const extra = useMemo(
222
- () => ({
223
- onChange: trackId => view.toggleTrack(trackId),
224
- toggleCollapse: pathName => model.toggleCategory(pathName),
225
- onMoreInfo: setMoreInfo,
226
- drawerPosition,
227
- }),
228
- [view, model, drawerPosition],
229
- )
230
- const treeWalker = useCallback(
231
- function* treeWalker() {
232
- for (let i = 0; i < tree.children.length; i++) {
233
- yield getNodeData(tree.children[i], 0, extra)
234
- }
254
+ const HierarchicalTree = observer(
255
+ ({
256
+ height,
257
+ tree,
258
+ model,
259
+ }: {
260
+ height: number
261
+ tree: TreeNode
262
+ model: HierarchicalTrackSelectorModel
263
+ }) => {
264
+ const { filterText, view } = model
265
+ const treeRef = useRef<NodeData>(null)
266
+ const [info, setMoreInfo] = useState<MoreInfoArgs>()
267
+ const session = getSession(model)
268
+ const { drawerPosition } = session
269
+
270
+ const extra = useMemo(
271
+ () => ({
272
+ onChange: (trackId: string) => view.toggleTrack(trackId),
273
+ toggleCollapse: (pathName: string) => model.toggleCategory(pathName),
274
+ onMoreInfo: setMoreInfo,
275
+ drawerPosition,
276
+ }),
277
+ [view, model, drawerPosition],
278
+ )
279
+ const treeWalker = useCallback(
280
+ function* treeWalker() {
281
+ for (let i = 0; i < tree.children.length; i++) {
282
+ const r = tree.children[i]
283
+ yield getNodeData(r, 0, extra)
284
+ }
235
285
 
236
- while (true) {
237
- const parentMeta = yield
286
+ while (true) {
287
+ // @ts-ignore
288
+ const parentMeta = yield
238
289
 
239
- for (let i = 0; i < parentMeta.node.children.length; i++) {
240
- const curr = parentMeta.node.children[i]
241
- yield getNodeData(curr, parentMeta.nestingLevel + 1, extra)
290
+ for (let i = 0; i < parentMeta.node.children.length; i++) {
291
+ const curr = parentMeta.node.children[i]
292
+ yield getNodeData(curr, parentMeta.nestingLevel + 1, extra)
293
+ }
242
294
  }
243
- }
244
- },
245
- [tree, extra],
246
- )
295
+ },
296
+ [tree, extra],
297
+ )
247
298
 
248
- const conf = info?.conf
249
- const menuItems = (conf && session.getTrackActionMenuItems?.(conf)) || []
299
+ const conf = info?.conf
300
+ const menuItems = (conf && session.getTrackActionMenuItems?.(conf)) || []
250
301
 
251
- useEffect(() => {
252
- treeRef.current.recomputeTree({
253
- refreshNodes: true,
254
- useDefaultHeight: true,
255
- })
256
- }, [tree, filterText])
257
- return (
258
- <>
259
- <VariableSizeTree ref={treeRef} treeWalker={treeWalker} height={height}>
260
- {Node}
261
- </VariableSizeTree>
262
- <JBrowseMenu
263
- anchorEl={info?.target}
264
- menuItems={menuItems}
265
- onMenuItemClick={(_event, callback) => {
266
- callback()
267
- setMoreInfo(undefined)
268
- }}
269
- open={Boolean(info)}
270
- onClose={() => setMoreInfo(undefined)}
271
- />
272
- </>
273
- )
274
- })
302
+ useEffect(() => {
303
+ // @ts-ignore
304
+ treeRef.current.recomputeTree({
305
+ refreshNodes: true,
306
+ useDefaultHeight: true,
307
+ })
308
+ }, [tree, filterText])
309
+ return (
310
+ <>
311
+ {/* @ts-ignore */}
312
+ <VariableSizeTree ref={treeRef} treeWalker={treeWalker} height={height}>
313
+ {/* @ts-ignore */}
314
+ {Node}
315
+ </VariableSizeTree>
316
+ <JBrowseMenu
317
+ anchorEl={info?.target}
318
+ menuItems={menuItems}
319
+ onMenuItemClick={(_event, callback) => {
320
+ callback()
321
+ setMoreInfo(undefined)
322
+ }}
323
+ open={Boolean(info)}
324
+ onClose={() => setMoreInfo(undefined)}
325
+ />
326
+ </>
327
+ )
328
+ },
329
+ )
275
330
 
276
331
  // Don't use autosizer in jest and instead hardcode a height, otherwise fails
277
332
  // jest tests
278
- const AutoSizedHierarchicalTree = ({ tree, model, offset }) => {
333
+ const AutoSizedHierarchicalTree = ({
334
+ tree,
335
+ model,
336
+ offset,
337
+ }: {
338
+ tree: TreeNode
339
+ model: HierarchicalTrackSelectorModel
340
+ offset: number
341
+ }) => {
279
342
  return typeof jest === 'undefined' ? (
280
343
  <AutoSizer disableWidth>
281
344
  {({ height }) => {
@@ -293,7 +356,13 @@ const AutoSizedHierarchicalTree = ({ tree, model, offset }) => {
293
356
  )
294
357
  }
295
358
 
296
- const Wrapper = ({ overrideDimensions, children }) => {
359
+ const Wrapper = ({
360
+ overrideDimensions,
361
+ children,
362
+ }: {
363
+ overrideDimensions?: { width: number; height: number }
364
+ children: React.ReactNode
365
+ }) => {
297
366
  return overrideDimensions ? (
298
367
  <div style={{ ...overrideDimensions }}>{children}</div>
299
368
  ) : (
@@ -301,29 +370,36 @@ const Wrapper = ({ overrideDimensions, children }) => {
301
370
  )
302
371
  }
303
372
  const HierarchicalTrackSelectorContainer = observer(
304
- ({ model, toolbarHeight, overrideDimensions }) => {
373
+ ({
374
+ model,
375
+ toolbarHeight,
376
+ overrideDimensions,
377
+ }: {
378
+ model: HierarchicalTrackSelectorModel
379
+ toolbarHeight: number
380
+ overrideDimensions?: { width: number; height: number }
381
+ }) => {
305
382
  const classes = useStyles()
306
383
  const session = getSession(model)
307
- const [anchorEl, setAnchorEl] = useState(null)
384
+ const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null)
308
385
 
309
386
  function handleFabClose() {
310
387
  setAnchorEl(null)
311
388
  }
389
+ const hasConnections = isSessionModelWithConnections(session)
390
+ const hasAddTrack = isSessionWithAddTracks(session)
312
391
  return (
313
392
  <Wrapper overrideDimensions={overrideDimensions}>
314
393
  <HierarchicalTrackSelector
315
394
  model={model}
316
395
  toolbarHeight={toolbarHeight}
317
- overrideDimensions={overrideDimensions}
318
396
  />
319
- {session.addConnectionConf || session.addTrackConf ? (
397
+ {hasAddTrack || hasConnections ? (
320
398
  <>
321
399
  <Fab
322
400
  color="secondary"
323
401
  className={classes.fab}
324
- onClick={event => {
325
- setAnchorEl(event.currentTarget)
326
- }}
402
+ onClick={event => setAnchorEl(event.currentTarget)}
327
403
  >
328
404
  <AddIcon />
329
405
  </Fab>
@@ -332,32 +408,34 @@ const HierarchicalTrackSelectorContainer = observer(
332
408
  open={Boolean(anchorEl)}
333
409
  onClose={() => setAnchorEl(null)}
334
410
  >
335
- {session.addConnectionConf ? (
411
+ {hasConnections ? (
336
412
  <MenuItem
337
413
  onClick={() => {
338
414
  handleFabClose()
339
- const widget = session.addWidget(
340
- 'AddConnectionWidget',
341
- 'addConnectionWidget',
342
- )
343
- session.showWidget(widget)
415
+ if (isSessionModelWithWidgets(session)) {
416
+ session.showWidget(
417
+ session.addWidget(
418
+ 'AddConnectionWidget',
419
+ 'addConnectionWidget',
420
+ ),
421
+ )
422
+ }
344
423
  }}
345
424
  >
346
425
  Add connection
347
426
  </MenuItem>
348
427
  ) : null}
349
- {session.addTrackConf ? (
428
+ {hasAddTrack ? (
350
429
  <MenuItem
351
430
  onClick={() => {
352
431
  handleFabClose()
353
- const widget = session.addWidget(
354
- 'AddTrackWidget',
355
- 'addTrackWidget',
356
- {
357
- view: model.view.id,
358
- },
359
- )
360
- session.showWidget(widget)
432
+ if (isSessionModelWithWidgets(session)) {
433
+ session.showWidget(
434
+ session.addWidget('AddTrackWidget', 'addTrackWidget', {
435
+ view: model.view.id,
436
+ }),
437
+ )
438
+ }
361
439
  }}
362
440
  >
363
441
  Add track
@@ -372,20 +450,44 @@ const HierarchicalTrackSelectorContainer = observer(
372
450
  )
373
451
 
374
452
  const HierarchicalTrackSelectorHeader = observer(
375
- ({ model, setHeaderHeight, setAssemblyIdx, assemblyIdx }) => {
453
+ ({
454
+ model,
455
+ setHeaderHeight,
456
+ setAssemblyIdx,
457
+ assemblyIdx,
458
+ }: {
459
+ model: HierarchicalTrackSelectorModel
460
+ setHeaderHeight: (n: number) => void
461
+ setAssemblyIdx: (n: number) => void
462
+ assemblyIdx: number
463
+ }) => {
376
464
  const classes = useStyles()
377
465
  const session = getSession(model)
378
- const [connectionAnchorEl, setConnectionAnchorEl] = useState()
379
- const [menuAnchorEl, setMenuAnchorEl] = useState()
380
- const [modalInfo, setModalInfo] = useState()
381
- const [deleteDialogDetails, setDeleteDialogDetails] = useState()
466
+ const [connectionAnchorEl, setConnectionAnchorEl] =
467
+ useState<HTMLButtonElement>()
468
+ const [menuAnchorEl, setMenuAnchorEl] = useState<HTMLButtonElement>()
469
+ const [modalInfo, setModalInfo] = useState<{
470
+ connectionConf: AnyConfigurationModel
471
+ safelyBreakConnection: Function
472
+ dereferenceTypeCount: { [key: string]: number }
473
+ name: string
474
+ }>()
475
+ const [deleteDialogDetails, setDeleteDialogDetails] = useState<{
476
+ name: string
477
+ connectionConf: AnyConfigurationModel
478
+ }>()
382
479
  const [connectionManagerOpen, setConnectionManagerOpen] = useState(false)
383
480
  const [connectionToggleOpen, setConnectionToggleOpen] = useState(false)
384
481
  const { assemblyNames } = model
385
482
  const assemblyName = assemblyNames[assemblyIdx]
386
483
 
387
- function breakConnection(connectionConf, deletingConnection) {
484
+ function breakConnection(
485
+ connectionConf: AnyConfigurationModel,
486
+ deletingConnection?: boolean,
487
+ ) {
388
488
  const name = readConfObject(connectionConf, 'name')
489
+
490
+ // @ts-ignore
389
491
  const result = session.prepareToBreakConnection(connectionConf)
390
492
  if (result) {
391
493
  const [safelyBreakConnection, dereferenceTypeCount] = result
@@ -412,13 +514,17 @@ const HierarchicalTrackSelectorHeader = observer(
412
514
  },
413
515
  ]
414
516
 
415
- if (session.addConnectionConf) {
517
+ if (isSessionModelWithConnections(session)) {
416
518
  connectionMenuItems.unshift({
417
519
  label: 'Add connection',
418
520
  onClick: () => {
419
- session.showWidget(
420
- session.addWidget('AddConnectionWidget', 'addConnectionWidget'),
421
- )
521
+ if (isSessionModelWithWidgets(session)) {
522
+ const widget = session.addWidget(
523
+ 'AddConnectionWidget',
524
+ 'addConnectionWidget',
525
+ )
526
+ session.showWidget(widget)
527
+ }
422
528
  },
423
529
  })
424
530
 
@@ -435,9 +541,7 @@ const HierarchicalTrackSelectorHeader = observer(
435
541
  label: 'Select assembly...',
436
542
  subMenu: assemblyNames.map((name, idx) => ({
437
543
  label: name,
438
- onClick: () => {
439
- setAssemblyIdx(idx)
440
- },
544
+ onClick: () => setAssemblyIdx(idx),
441
545
  })),
442
546
  },
443
547
  ]
@@ -447,11 +551,16 @@ const HierarchicalTrackSelectorHeader = observer(
447
551
  {
448
552
  label: 'Add track...',
449
553
  onClick: () => {
450
- session.showWidget(
451
- session.addWidget('AddTrackWidget', 'addTrackWidget', {
452
- view: model.view.id,
453
- }),
454
- )
554
+ if (isSessionModelWithWidgets(session)) {
555
+ const widget = session.addWidget(
556
+ 'AddTrackWidget',
557
+ 'addTrackWidget',
558
+ {
559
+ view: model.view.id,
560
+ },
561
+ )
562
+ session.showWidget(widget)
563
+ }
455
564
  },
456
565
  },
457
566
 
@@ -464,12 +573,10 @@ const HierarchicalTrackSelectorHeader = observer(
464
573
  data-testid="hierarchical_track_selector"
465
574
  >
466
575
  <div style={{ display: 'flex' }}>
467
- {session.addTrackConf && (
576
+ {isSessionWithAddTracks(session) && (
468
577
  <IconButton
469
578
  className={classes.menuIcon}
470
- onClick={event => {
471
- setMenuAnchorEl(event.currentTarget)
472
- }}
579
+ onClick={event => setMenuAnchorEl(event.currentTarget)}
473
580
  >
474
581
  <MenuIcon />
475
582
  </IconButton>
@@ -478,9 +585,7 @@ const HierarchicalTrackSelectorHeader = observer(
478
585
  {session.makeConnection && (
479
586
  <IconButton
480
587
  className={classes.menuIcon}
481
- onClick={event => {
482
- setConnectionAnchorEl(event.currentTarget)
483
- }}
588
+ onClick={event => setConnectionAnchorEl(event.currentTarget)}
484
589
  >
485
590
  <Cable />
486
591
  </IconButton>
@@ -528,7 +633,6 @@ const HierarchicalTrackSelectorHeader = observer(
528
633
  <CloseConnectionDialog
529
634
  modalInfo={modalInfo}
530
635
  setModalInfo={setModalInfo}
531
- session={session}
532
636
  />
533
637
  ) : deleteDialogDetails ? (
534
638
  <DeleteConnectionDialog
@@ -557,27 +661,35 @@ const HierarchicalTrackSelectorHeader = observer(
557
661
  )
558
662
  },
559
663
  )
560
- const HierarchicalTrackSelector = observer(({ model, toolbarHeight = 0 }) => {
561
- const [assemblyIdx, setAssemblyIdx] = useState(0)
562
- const [headerHeight, setHeaderHeight] = useState(0)
563
-
564
- const { assemblyNames } = model
565
- const assemblyName = assemblyNames[assemblyIdx]
566
- return assemblyName ? (
567
- <>
568
- <HierarchicalTrackSelectorHeader
569
- model={model}
570
- setHeaderHeight={setHeaderHeight}
571
- setAssemblyIdx={setAssemblyIdx}
572
- assemblyIdx={assemblyIdx}
573
- />
574
- <AutoSizedHierarchicalTree
575
- tree={model.hierarchy(assemblyName)}
576
- model={model}
577
- offset={toolbarHeight + headerHeight}
578
- />
579
- </>
580
- ) : null
581
- })
664
+ const HierarchicalTrackSelector = observer(
665
+ ({
666
+ model,
667
+ toolbarHeight = 0,
668
+ }: {
669
+ model: HierarchicalTrackSelectorModel
670
+ toolbarHeight?: number
671
+ }) => {
672
+ const [assemblyIdx, setAssemblyIdx] = useState(0)
673
+ const [headerHeight, setHeaderHeight] = useState(0)
674
+
675
+ const { assemblyNames } = model
676
+ const assemblyName = assemblyNames[assemblyIdx]
677
+ return assemblyName ? (
678
+ <>
679
+ <HierarchicalTrackSelectorHeader
680
+ model={model}
681
+ setHeaderHeight={setHeaderHeight}
682
+ setAssemblyIdx={setAssemblyIdx}
683
+ assemblyIdx={assemblyIdx}
684
+ />
685
+ <AutoSizedHierarchicalTree
686
+ tree={model.hierarchy(assemblyName)}
687
+ model={model}
688
+ offset={toolbarHeight + headerHeight}
689
+ />
690
+ </>
691
+ ) : null
692
+ },
693
+ )
582
694
 
583
695
  export default HierarchicalTrackSelectorContainer
@@ -12,7 +12,10 @@ import {
12
12
  } from '@material-ui/core'
13
13
  import CloseIcon from '@material-ui/icons/Close'
14
14
  import { observer } from 'mobx-react'
15
- import { readConfObject } from '@jbrowse/core/configuration'
15
+ import {
16
+ AnyConfigurationModel,
17
+ readConfObject,
18
+ } from '@jbrowse/core/configuration'
16
19
  import { AbstractSessionModel } from '@jbrowse/core/util'
17
20
 
18
21
  const useStyles = makeStyles(theme => ({
@@ -36,7 +39,7 @@ function ManageConnectionsDlg({
36
39
  }: {
37
40
  handleClose: () => void
38
41
  session: AbstractSessionModel
39
- breakConnection: Function
42
+ breakConnection: (conf: AnyConfigurationModel, arg: boolean) => void
40
43
  }) {
41
44
  const classes = useStyles()
42
45
  const { adminMode, connections, sessionConnections } = session
@@ -13,7 +13,10 @@ import {
13
13
  } from '@material-ui/core'
14
14
  import CloseIcon from '@material-ui/icons/Close'
15
15
  import { observer } from 'mobx-react'
16
- import { readConfObject } from '@jbrowse/core/configuration'
16
+ import {
17
+ AnyConfigurationModel,
18
+ readConfObject,
19
+ } from '@jbrowse/core/configuration'
17
20
  import { AbstractSessionModel } from '@jbrowse/core/util'
18
21
 
19
22
  const useStyles = makeStyles(theme => ({
@@ -39,10 +42,10 @@ function ToggleConnectionDialog({
39
42
  handleClose: () => void
40
43
  session: AbstractSessionModel
41
44
  assemblyName: string
42
- breakConnection: Function
45
+ breakConnection: (arg: AnyConfigurationModel) => void
43
46
  }) {
44
47
  const classes = useStyles()
45
- const { connections, connectionInstances } = session
48
+ const { connections, connectionInstances: instances = [] } = session
46
49
  const assemblySpecificConnections = connections.filter(c => {
47
50
  const configAssemblyNames = readConfObject(c, 'assemblyNames')
48
51
  if (configAssemblyNames.length === 0) {
@@ -50,6 +53,7 @@ function ToggleConnectionDialog({
50
53
  }
51
54
  return configAssemblyNames.includes(assemblyName)
52
55
  })
56
+
53
57
  return (
54
58
  <Dialog open onClose={handleClose} maxWidth="lg">
55
59
  <DialogTitle>
@@ -66,31 +70,25 @@ function ToggleConnectionDialog({
66
70
  <div className={classes.connectionContainer}>
67
71
  {assemblySpecificConnections.map(conf => {
68
72
  const name = readConfObject(conf, 'name')
73
+ const found = instances.find(conn => name === conn.name)
69
74
  return (
70
- <div key={conf.connectionId}>
71
- <FormControlLabel
72
- control={
73
- <Checkbox
74
- checked={
75
- !!connectionInstances?.find(conn => name === conn.name)
75
+ <FormControlLabel
76
+ key={conf.connectionId}
77
+ control={
78
+ <Checkbox
79
+ checked={!!found}
80
+ onChange={() => {
81
+ if (found) {
82
+ breakConnection(conf)
83
+ } else {
84
+ session.makeConnection?.(conf)
76
85
  }
77
- onChange={() => {
78
- if (
79
- connectionInstances?.find(
80
- conn => conn.name === readConfObject(conf, 'name'),
81
- )
82
- ) {
83
- breakConnection(conf)
84
- } else {
85
- session.makeConnection?.(conf)
86
- }
87
- }}
88
- color="primary"
89
- />
90
- }
91
- label={name}
92
- />
93
- </div>
86
+ }}
87
+ color="primary"
88
+ />
89
+ }
90
+ label={name}
91
+ />
94
92
  )
95
93
  })}
96
94
  {!assemblySpecificConnections.length ? (