@jbrowse/product-core 2.6.1
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/LICENSE +201 -0
- package/dist/RootModel/BaseRootModel.d.ts +607 -0
- package/dist/RootModel/BaseRootModel.js +101 -0
- package/dist/RootModel/InternetAccounts.d.ts +31 -0
- package/dist/RootModel/InternetAccounts.js +99 -0
- package/dist/RootModel/index.d.ts +2 -0
- package/dist/RootModel/index.js +18 -0
- package/dist/Session/BaseSession.d.ts +99 -0
- package/dist/Session/BaseSession.js +112 -0
- package/dist/Session/Connections.d.ts +174 -0
- package/dist/Session/Connections.js +113 -0
- package/dist/Session/DialogQueue.d.ts +34 -0
- package/dist/Session/DialogQueue.js +55 -0
- package/dist/Session/DrawerWidgets.d.ts +88 -0
- package/dist/Session/DrawerWidgets.js +167 -0
- package/dist/Session/MultipleViews.d.ts +1798 -0
- package/dist/Session/MultipleViews.js +105 -0
- package/dist/Session/ReferenceManagement.d.ts +34 -0
- package/dist/Session/ReferenceManagement.js +91 -0
- package/dist/Session/SessionTracks.d.ts +1866 -0
- package/dist/Session/SessionTracks.js +75 -0
- package/dist/Session/Themes.d.ts +38 -0
- package/dist/Session/Themes.js +64 -0
- package/dist/Session/Tracks.d.ts +1821 -0
- package/dist/Session/Tracks.js +51 -0
- package/dist/Session/index.d.ts +10 -0
- package/dist/Session/index.js +26 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +19 -0
- package/dist/ui/AboutDialog.d.ts +6 -0
- package/dist/ui/AboutDialog.js +20 -0
- package/dist/ui/AboutDialogContents.d.ts +5 -0
- package/dist/ui/AboutDialogContents.js +70 -0
- package/dist/ui/FileInfoPanel.d.ts +5 -0
- package/dist/ui/FileInfoPanel.js +76 -0
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.js +17 -0
- package/esm/RootModel/BaseRootModel.d.ts +607 -0
- package/esm/RootModel/BaseRootModel.js +93 -0
- package/esm/RootModel/InternetAccounts.d.ts +31 -0
- package/esm/RootModel/InternetAccounts.js +95 -0
- package/esm/RootModel/index.d.ts +2 -0
- package/esm/RootModel/index.js +2 -0
- package/esm/Session/BaseSession.d.ts +99 -0
- package/esm/Session/BaseSession.js +103 -0
- package/esm/Session/Connections.d.ts +174 -0
- package/esm/Session/Connections.js +108 -0
- package/esm/Session/DialogQueue.d.ts +34 -0
- package/esm/Session/DialogQueue.js +50 -0
- package/esm/Session/DrawerWidgets.d.ts +88 -0
- package/esm/Session/DrawerWidgets.js +162 -0
- package/esm/Session/MultipleViews.d.ts +1798 -0
- package/esm/Session/MultipleViews.js +100 -0
- package/esm/Session/ReferenceManagement.d.ts +34 -0
- package/esm/Session/ReferenceManagement.js +86 -0
- package/esm/Session/SessionTracks.d.ts +1866 -0
- package/esm/Session/SessionTracks.js +70 -0
- package/esm/Session/Themes.d.ts +38 -0
- package/esm/Session/Themes.js +59 -0
- package/esm/Session/Tracks.d.ts +1821 -0
- package/esm/Session/Tracks.js +46 -0
- package/esm/Session/index.d.ts +10 -0
- package/esm/Session/index.js +10 -0
- package/esm/index.d.ts +3 -0
- package/esm/index.js +3 -0
- package/esm/ui/AboutDialog.d.ts +6 -0
- package/esm/ui/AboutDialog.js +13 -0
- package/esm/ui/AboutDialogContents.d.ts +5 -0
- package/esm/ui/AboutDialogContents.js +41 -0
- package/esm/ui/FileInfoPanel.d.ts +5 -0
- package/esm/ui/FileInfoPanel.js +47 -0
- package/esm/ui/index.d.ts +1 -0
- package/esm/ui/index.js +1 -0
- package/package.json +66 -0
- package/src/RootModel/BaseRootModel.ts +131 -0
- package/src/RootModel/InternetAccounts.ts +126 -0
- package/src/RootModel/index.ts +2 -0
- package/src/Session/BaseSession.ts +129 -0
- package/src/Session/Connections.ts +145 -0
- package/src/Session/DialogQueue.ts +63 -0
- package/src/Session/DrawerWidgets.ts +222 -0
- package/src/Session/MultipleViews.ts +151 -0
- package/src/Session/ReferenceManagement.ts +134 -0
- package/src/Session/SessionTracks.ts +98 -0
- package/src/Session/Themes.ts +85 -0
- package/src/Session/Tracks.ts +72 -0
- package/src/Session/index.ts +10 -0
- package/src/index.ts +3 -0
- package/src/ui/AboutDialog.tsx +31 -0
- package/src/ui/AboutDialogContents.tsx +88 -0
- package/src/ui/FileInfoPanel.tsx +75 -0
- package/src/ui/index.ts +1 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { IAnyStateTreeNode, Instance, types } from 'mobx-state-tree'
|
|
2
|
+
|
|
3
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
4
|
+
import {
|
|
5
|
+
AnyConfiguration,
|
|
6
|
+
AnyConfigurationModel,
|
|
7
|
+
} from '@jbrowse/core/configuration'
|
|
8
|
+
|
|
9
|
+
// locals
|
|
10
|
+
import { TracksManagerSessionMixin } from './Tracks'
|
|
11
|
+
import { isBaseSession } from './BaseSession'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* #stateModel SessionTracksManagerSessionMixin
|
|
15
|
+
*/
|
|
16
|
+
export function SessionTracksManagerSessionMixin(pluginManager: PluginManager) {
|
|
17
|
+
return TracksManagerSessionMixin(pluginManager)
|
|
18
|
+
.named('SessionTracksManagerSessionMixin')
|
|
19
|
+
.props({
|
|
20
|
+
/**
|
|
21
|
+
* #property
|
|
22
|
+
*/
|
|
23
|
+
sessionTracks: types.array(
|
|
24
|
+
pluginManager.pluggableConfigSchemaType('track'),
|
|
25
|
+
),
|
|
26
|
+
})
|
|
27
|
+
.views(self => ({
|
|
28
|
+
/**
|
|
29
|
+
* #getter
|
|
30
|
+
*/
|
|
31
|
+
get tracks(): AnyConfigurationModel[] {
|
|
32
|
+
return self.jbrowse.tracks
|
|
33
|
+
},
|
|
34
|
+
}))
|
|
35
|
+
.actions(self => {
|
|
36
|
+
const {
|
|
37
|
+
addTrackConf: superAddTrackConf,
|
|
38
|
+
deleteTrackConf: superDeleteTrackConf,
|
|
39
|
+
} = self
|
|
40
|
+
return {
|
|
41
|
+
/**
|
|
42
|
+
* #action
|
|
43
|
+
*/
|
|
44
|
+
addTrackConf(trackConf: AnyConfiguration) {
|
|
45
|
+
if (self.adminMode) {
|
|
46
|
+
return superAddTrackConf(trackConf)
|
|
47
|
+
}
|
|
48
|
+
const { trackId, type } = trackConf as {
|
|
49
|
+
type: string
|
|
50
|
+
trackId: string
|
|
51
|
+
}
|
|
52
|
+
if (!type) {
|
|
53
|
+
throw new Error(`unknown track type ${type}`)
|
|
54
|
+
}
|
|
55
|
+
const track = self.sessionTracks.find(t => t.trackId === trackId)
|
|
56
|
+
if (track) {
|
|
57
|
+
return track
|
|
58
|
+
}
|
|
59
|
+
const length = self.sessionTracks.push(trackConf)
|
|
60
|
+
return self.sessionTracks[length - 1]
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* #action
|
|
65
|
+
*/
|
|
66
|
+
deleteTrackConf(trackConf: AnyConfigurationModel) {
|
|
67
|
+
// try to delete it in the main config if in admin mode
|
|
68
|
+
const found = superDeleteTrackConf(trackConf)
|
|
69
|
+
if (found) {
|
|
70
|
+
return found
|
|
71
|
+
}
|
|
72
|
+
// if not found or not in admin mode, try to delete it in the
|
|
73
|
+
// sessionTracks
|
|
74
|
+
const { trackId } = trackConf
|
|
75
|
+
const idx = self.sessionTracks.findIndex(t => t.trackId === trackId)
|
|
76
|
+
if (idx === -1) {
|
|
77
|
+
return undefined
|
|
78
|
+
}
|
|
79
|
+
return self.sessionTracks.splice(idx, 1)
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Session mixin MST type for a session that has `sessionTracks` */
|
|
86
|
+
export type SessionWithSessionTracksType = ReturnType<
|
|
87
|
+
typeof SessionTracksManagerSessionMixin
|
|
88
|
+
>
|
|
89
|
+
|
|
90
|
+
/** Instance of a session that has `sessionTracks` */
|
|
91
|
+
export type SessionWithSessionTracks = Instance<SessionWithSessionTracksType>
|
|
92
|
+
|
|
93
|
+
/** Type guard for SessionWithSessionTracks */
|
|
94
|
+
export function isSessionWithSessionTracks(
|
|
95
|
+
thing: IAnyStateTreeNode,
|
|
96
|
+
): thing is SessionWithSessionTracks {
|
|
97
|
+
return isBaseSession(thing) && 'sessionTracks' in thing
|
|
98
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IAnyStateTreeNode,
|
|
3
|
+
Instance,
|
|
4
|
+
addDisposer,
|
|
5
|
+
types,
|
|
6
|
+
} from 'mobx-state-tree'
|
|
7
|
+
|
|
8
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
9
|
+
import { getConf } from '@jbrowse/core/configuration'
|
|
10
|
+
import { createJBrowseTheme, defaultThemes } from '@jbrowse/core/ui'
|
|
11
|
+
import { localStorageGetItem, localStorageSetItem } from '@jbrowse/core/util'
|
|
12
|
+
import { ThemeOptions } from '@mui/material'
|
|
13
|
+
import { autorun } from 'mobx'
|
|
14
|
+
|
|
15
|
+
// locals
|
|
16
|
+
import { BaseSession } from './BaseSession'
|
|
17
|
+
|
|
18
|
+
type ThemeMap = { [key: string]: ThemeOptions }
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* #stateModel ThemeManagerSessionMixin
|
|
22
|
+
*/
|
|
23
|
+
export function ThemeManagerSessionMixin(pluginManager: PluginManager) {
|
|
24
|
+
return types
|
|
25
|
+
.model({})
|
|
26
|
+
.volatile(() => ({
|
|
27
|
+
sessionThemeName: localStorageGetItem('themeName') || 'default',
|
|
28
|
+
}))
|
|
29
|
+
.views(s => ({
|
|
30
|
+
/**
|
|
31
|
+
* #method
|
|
32
|
+
*/
|
|
33
|
+
allThemes(): ThemeMap {
|
|
34
|
+
const self = s as typeof s & BaseSession
|
|
35
|
+
const extraThemes = getConf(self.jbrowse, 'extraThemes')
|
|
36
|
+
return { ...defaultThemes, ...extraThemes }
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* #getter
|
|
40
|
+
*/
|
|
41
|
+
get themeName() {
|
|
42
|
+
const { sessionThemeName } = s
|
|
43
|
+
const all = this.allThemes()
|
|
44
|
+
return all[sessionThemeName] ? sessionThemeName : 'default'
|
|
45
|
+
},
|
|
46
|
+
/**
|
|
47
|
+
* #getter
|
|
48
|
+
*/
|
|
49
|
+
get theme() {
|
|
50
|
+
const self = s as typeof s & BaseSession
|
|
51
|
+
const configTheme = getConf(self.jbrowse, 'theme')
|
|
52
|
+
const all = this.allThemes()
|
|
53
|
+
return createJBrowseTheme(configTheme, all, this.themeName)
|
|
54
|
+
},
|
|
55
|
+
}))
|
|
56
|
+
.actions(self => ({
|
|
57
|
+
/**
|
|
58
|
+
* #action
|
|
59
|
+
*/
|
|
60
|
+
setThemeName(name: string) {
|
|
61
|
+
self.sessionThemeName = name
|
|
62
|
+
},
|
|
63
|
+
afterAttach() {
|
|
64
|
+
addDisposer(
|
|
65
|
+
self,
|
|
66
|
+
autorun(() => {
|
|
67
|
+
localStorageSetItem('themeName', self.themeName)
|
|
68
|
+
}),
|
|
69
|
+
)
|
|
70
|
+
},
|
|
71
|
+
}))
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Session mixin MST type for a session that supports theming */
|
|
75
|
+
export type SessionWithThemesType = ReturnType<typeof ThemeManagerSessionMixin>
|
|
76
|
+
|
|
77
|
+
/** Instance of a session that has theming support */
|
|
78
|
+
export type SessionWithThemes = Instance<SessionWithThemesType>
|
|
79
|
+
|
|
80
|
+
/** Type guard for SessionWithThemes */
|
|
81
|
+
export function isSessionWithThemes(
|
|
82
|
+
session: IAnyStateTreeNode,
|
|
83
|
+
): session is SessionWithThemes {
|
|
84
|
+
return 'theme' in session
|
|
85
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { IAnyStateTreeNode, Instance, types } from 'mobx-state-tree'
|
|
2
|
+
|
|
3
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
4
|
+
import {
|
|
5
|
+
AnyConfiguration,
|
|
6
|
+
AnyConfigurationModel,
|
|
7
|
+
} from '@jbrowse/core/configuration'
|
|
8
|
+
import { BaseSessionModel, isBaseSession } from './BaseSession'
|
|
9
|
+
import { ReferenceManagementSessionMixin } from './ReferenceManagement'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* #stateModel TracksManagerSessionMixin
|
|
13
|
+
* composed of
|
|
14
|
+
* - BaseSessionModel
|
|
15
|
+
* - ReferenceManagementSessionMixin
|
|
16
|
+
*/
|
|
17
|
+
export function TracksManagerSessionMixin(pluginManager: PluginManager) {
|
|
18
|
+
return types
|
|
19
|
+
.compose(
|
|
20
|
+
'TracksManagerSessionMixin',
|
|
21
|
+
BaseSessionModel(pluginManager),
|
|
22
|
+
ReferenceManagementSessionMixin(pluginManager),
|
|
23
|
+
)
|
|
24
|
+
.views(self => ({
|
|
25
|
+
/**
|
|
26
|
+
* #getter
|
|
27
|
+
*/
|
|
28
|
+
get tracks(): AnyConfigurationModel[] {
|
|
29
|
+
return self.jbrowse.tracks
|
|
30
|
+
},
|
|
31
|
+
}))
|
|
32
|
+
.actions(self => ({
|
|
33
|
+
/**
|
|
34
|
+
* #action
|
|
35
|
+
*/
|
|
36
|
+
addTrackConf(trackConf: AnyConfiguration) {
|
|
37
|
+
return self.jbrowse.addTrackConf(trackConf)
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* #action
|
|
42
|
+
*/
|
|
43
|
+
deleteTrackConf(trackConf: AnyConfigurationModel) {
|
|
44
|
+
const callbacksToDereferenceTrack: Function[] = []
|
|
45
|
+
const dereferenceTypeCount: Record<string, number> = {}
|
|
46
|
+
const referring = self.getReferring(trackConf)
|
|
47
|
+
self.removeReferring(
|
|
48
|
+
referring,
|
|
49
|
+
trackConf,
|
|
50
|
+
callbacksToDereferenceTrack,
|
|
51
|
+
dereferenceTypeCount,
|
|
52
|
+
)
|
|
53
|
+
callbacksToDereferenceTrack.forEach(cb => cb())
|
|
54
|
+
if (self.adminMode) {
|
|
55
|
+
return self.jbrowse.deleteTrackConf(trackConf)
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
}))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Session mixin MST type for a session that has tracks */
|
|
62
|
+
export type SessionWithTracksType = ReturnType<typeof TracksManagerSessionMixin>
|
|
63
|
+
|
|
64
|
+
/** Instance of a session that has tracks */
|
|
65
|
+
export type SessionWithTracks = Instance<SessionWithTracksType>
|
|
66
|
+
|
|
67
|
+
/** Type guard for SessionWithTracks */
|
|
68
|
+
export function isSessionWithTracks(
|
|
69
|
+
thing: IAnyStateTreeNode,
|
|
70
|
+
): thing is SessionWithTracks {
|
|
71
|
+
return isBaseSession(thing) && 'tracks' in thing
|
|
72
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './ReferenceManagement'
|
|
2
|
+
export * from './Connections'
|
|
3
|
+
export * from './DrawerWidgets'
|
|
4
|
+
export * from './DialogQueue'
|
|
5
|
+
export * from './Themes'
|
|
6
|
+
export * from './Tracks'
|
|
7
|
+
export * from './MultipleViews'
|
|
8
|
+
export * from './BaseSession'
|
|
9
|
+
export * from './SessionTracks'
|
|
10
|
+
export * from './BaseSession'
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { AnyConfigurationModel } from '@jbrowse/core/configuration'
|
|
3
|
+
import Dialog from '@jbrowse/core/ui/Dialog'
|
|
4
|
+
import { getSession, getEnv } from '@jbrowse/core/util'
|
|
5
|
+
import { getTrackName } from '@jbrowse/core/util/tracks'
|
|
6
|
+
import AboutContents from './AboutDialogContents'
|
|
7
|
+
|
|
8
|
+
export function AboutDialog({
|
|
9
|
+
config,
|
|
10
|
+
handleClose,
|
|
11
|
+
}: {
|
|
12
|
+
config: AnyConfigurationModel
|
|
13
|
+
handleClose: () => void
|
|
14
|
+
}) {
|
|
15
|
+
const session = getSession(config)
|
|
16
|
+
const trackName = getTrackName(config, session)
|
|
17
|
+
const { pluginManager } = getEnv(session)
|
|
18
|
+
|
|
19
|
+
const AboutComponent = pluginManager.evaluateExtensionPoint(
|
|
20
|
+
'Core-replaceAbout',
|
|
21
|
+
AboutContents,
|
|
22
|
+
{ session, config },
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
+
) as React.FC<any>
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<Dialog open onClose={handleClose} title={trackName} maxWidth="xl">
|
|
28
|
+
<AboutComponent config={config} />
|
|
29
|
+
</Dialog>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import copy from 'copy-to-clipboard'
|
|
3
|
+
import { Button } from '@mui/material'
|
|
4
|
+
import { makeStyles } from 'tss-react/mui'
|
|
5
|
+
import {
|
|
6
|
+
getConf,
|
|
7
|
+
readConfObject,
|
|
8
|
+
AnyConfigurationModel,
|
|
9
|
+
} from '@jbrowse/core/configuration'
|
|
10
|
+
import { getSession, getEnv } from '@jbrowse/core/util'
|
|
11
|
+
import {
|
|
12
|
+
BaseCard,
|
|
13
|
+
Attributes,
|
|
14
|
+
} from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
|
|
15
|
+
import FileInfoPanel from './FileInfoPanel'
|
|
16
|
+
|
|
17
|
+
const useStyles = makeStyles()({
|
|
18
|
+
content: {
|
|
19
|
+
minWidth: 800,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
export default function AboutContents({
|
|
24
|
+
config,
|
|
25
|
+
}: {
|
|
26
|
+
config: AnyConfigurationModel
|
|
27
|
+
}) {
|
|
28
|
+
const [copied, setCopied] = useState(false)
|
|
29
|
+
const conf = readConfObject(config)
|
|
30
|
+
const session = getSession(config)
|
|
31
|
+
const { classes } = useStyles()
|
|
32
|
+
|
|
33
|
+
const hideUris =
|
|
34
|
+
getConf(session, ['formatAbout', 'hideUris']) ||
|
|
35
|
+
readConfObject(config, ['formatAbout', 'hideUris'])
|
|
36
|
+
|
|
37
|
+
const { pluginManager } = getEnv(session)
|
|
38
|
+
|
|
39
|
+
const confPostExt = pluginManager.evaluateExtensionPoint(
|
|
40
|
+
'Core-customizeAbout',
|
|
41
|
+
{
|
|
42
|
+
config: {
|
|
43
|
+
...conf,
|
|
44
|
+
...getConf(session, ['formatAbout', 'config'], { config: conf }),
|
|
45
|
+
...readConfObject(config, ['formatAbout', 'config'], { config: conf }),
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{ session, config },
|
|
49
|
+
) as Record<string, unknown>
|
|
50
|
+
|
|
51
|
+
const ExtraPanel = pluginManager.evaluateExtensionPoint(
|
|
52
|
+
'Core-extraAboutPanel',
|
|
53
|
+
null,
|
|
54
|
+
{ session, config },
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
56
|
+
) as { name: string; Component: React.FC<any> }
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<div className={classes.content}>
|
|
60
|
+
<BaseCard title="Configuration">
|
|
61
|
+
{!hideUris ? (
|
|
62
|
+
<Button
|
|
63
|
+
variant="contained"
|
|
64
|
+
style={{ float: 'right' }}
|
|
65
|
+
onClick={() => {
|
|
66
|
+
copy(JSON.stringify(conf, null, 2))
|
|
67
|
+
setCopied(true)
|
|
68
|
+
setTimeout(() => setCopied(false), 1000)
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
{copied ? 'Copied to clipboard!' : 'Copy config'}
|
|
72
|
+
</Button>
|
|
73
|
+
) : null}
|
|
74
|
+
<Attributes
|
|
75
|
+
attributes={confPostExt}
|
|
76
|
+
omit={['displays', 'baseUri', 'refNames', 'formatAbout']}
|
|
77
|
+
hideUris={hideUris}
|
|
78
|
+
/>
|
|
79
|
+
</BaseCard>
|
|
80
|
+
{ExtraPanel ? (
|
|
81
|
+
<BaseCard title={ExtraPanel.name}>
|
|
82
|
+
<ExtraPanel.Component config={config} />
|
|
83
|
+
</BaseCard>
|
|
84
|
+
) : null}
|
|
85
|
+
<FileInfoPanel config={config} />
|
|
86
|
+
</div>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react'
|
|
2
|
+
import { Typography } from '@mui/material'
|
|
3
|
+
import {
|
|
4
|
+
readConfObject,
|
|
5
|
+
AnyConfigurationModel,
|
|
6
|
+
} from '@jbrowse/core/configuration'
|
|
7
|
+
import LoadingEllipses from '@jbrowse/core/ui/LoadingEllipses'
|
|
8
|
+
import { getSession } from '@jbrowse/core/util'
|
|
9
|
+
import {
|
|
10
|
+
BaseCard,
|
|
11
|
+
Attributes,
|
|
12
|
+
} from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
|
|
13
|
+
|
|
14
|
+
type FileInfo = Record<string, unknown> | string
|
|
15
|
+
|
|
16
|
+
export default function FileInfoPanel({
|
|
17
|
+
config,
|
|
18
|
+
}: {
|
|
19
|
+
config: AnyConfigurationModel
|
|
20
|
+
}) {
|
|
21
|
+
const [error, setError] = useState<unknown>()
|
|
22
|
+
const [info, setInfo] = useState<FileInfo>()
|
|
23
|
+
const session = getSession(config)
|
|
24
|
+
const { rpcManager } = session
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
const aborter = new AbortController()
|
|
28
|
+
const { signal } = aborter
|
|
29
|
+
let cancelled = false
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
31
|
+
;(async () => {
|
|
32
|
+
try {
|
|
33
|
+
const adapterConfig = readConfObject(config, 'adapter')
|
|
34
|
+
const result = await rpcManager.call(config.trackId, 'CoreGetInfo', {
|
|
35
|
+
adapterConfig,
|
|
36
|
+
signal,
|
|
37
|
+
})
|
|
38
|
+
if (!cancelled) {
|
|
39
|
+
setInfo(result as FileInfo)
|
|
40
|
+
}
|
|
41
|
+
} catch (e) {
|
|
42
|
+
if (!cancelled) {
|
|
43
|
+
console.error(e)
|
|
44
|
+
setError(e)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
})()
|
|
48
|
+
|
|
49
|
+
return () => {
|
|
50
|
+
aborter.abort()
|
|
51
|
+
cancelled = true
|
|
52
|
+
}
|
|
53
|
+
}, [config, rpcManager])
|
|
54
|
+
|
|
55
|
+
const details =
|
|
56
|
+
typeof info === 'string'
|
|
57
|
+
? {
|
|
58
|
+
header: `<pre>${info
|
|
59
|
+
.replaceAll('<', '<')
|
|
60
|
+
.replaceAll('>', '>')}</pre>`,
|
|
61
|
+
}
|
|
62
|
+
: info || {}
|
|
63
|
+
|
|
64
|
+
return info !== null ? (
|
|
65
|
+
<BaseCard title="File info">
|
|
66
|
+
{error ? (
|
|
67
|
+
<Typography color="error">{`${error}`}</Typography>
|
|
68
|
+
) : info === undefined ? (
|
|
69
|
+
<LoadingEllipses message="Loading file data" />
|
|
70
|
+
) : (
|
|
71
|
+
<Attributes attributes={details} />
|
|
72
|
+
)}
|
|
73
|
+
</BaseCard>
|
|
74
|
+
) : null
|
|
75
|
+
}
|
package/src/ui/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './AboutDialog'
|