@jbrowse/product-core 2.6.1 → 2.6.2

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.
@@ -1,145 +0,0 @@
1
- import PluginManager from '@jbrowse/core/PluginManager'
2
- import {
3
- AnyConfigurationModel,
4
- readConfObject,
5
- } from '@jbrowse/core/configuration'
6
- import { IAnyStateTreeNode, Instance, types } from 'mobx-state-tree'
7
- import { BaseConnectionConfigModel } from '@jbrowse/core/pluggableElementTypes/models/baseConnectionConfig'
8
- import { BaseConnectionModel } from '@jbrowse/core/pluggableElementTypes/models/BaseConnectionModelFactory'
9
-
10
- // locals
11
- import type { BaseRootModelType } from '../RootModel/BaseRootModel'
12
- import type { SessionWithReferenceManagementType } from './ReferenceManagement'
13
- import { isBaseSession } from './BaseSession'
14
-
15
- /**
16
- * #stateModel ConnectionManagementSessionMixin
17
- */
18
- export function ConnectionManagementSessionMixin(pluginManager: PluginManager) {
19
- return types
20
- .model({
21
- /**
22
- * #property
23
- */
24
- connectionInstances: types.array(
25
- pluginManager.pluggableMstType(
26
- 'connection',
27
- 'stateModel',
28
- ) as BaseConnectionModel,
29
- ),
30
- })
31
- .views(self => ({
32
- /**
33
- * #getter
34
- */
35
- get connections(): BaseConnectionConfigModel[] {
36
- const { jbrowse } = self as typeof self & Instance<BaseRootModelType>
37
- return jbrowse.connections
38
- },
39
- }))
40
- .actions(self => ({
41
- /**
42
- * #action
43
- */
44
- makeConnection(
45
- configuration: AnyConfigurationModel,
46
- initialSnapshot = {},
47
- ) {
48
- const type = configuration.type as string
49
- if (!type) {
50
- throw new Error('track configuration has no `type` listed')
51
- }
52
- const name = readConfObject(configuration, 'name')
53
- const connectionType = pluginManager.getConnectionType(type)
54
- if (!connectionType) {
55
- throw new Error(`unknown connection type ${type}`)
56
- }
57
- const length = self.connectionInstances.push({
58
- ...initialSnapshot,
59
- name,
60
- // @ts-expect-error unsure why ts doesn't like `type` here, but is
61
- // needed
62
- type,
63
- configuration,
64
- })
65
- return self.connectionInstances[length - 1]
66
- },
67
-
68
- /**
69
- * #action
70
- */
71
- prepareToBreakConnection(configuration: AnyConfigurationModel) {
72
- const root = self as typeof self &
73
- Instance<SessionWithReferenceManagementType>
74
- const callbacksToDeref: Function[] = []
75
- const derefTypeCount: Record<string, number> = {}
76
- const name = readConfObject(configuration, 'name')
77
- const connection = self.connectionInstances.find(c => c.name === name)
78
- if (!connection) {
79
- return undefined
80
- }
81
- for (const track of connection.tracks) {
82
- const ref = root.getReferring(track)
83
- root.removeReferring(ref, track, callbacksToDeref, derefTypeCount)
84
- }
85
- return [
86
- () => {
87
- callbacksToDeref.forEach(cb => cb())
88
- this.breakConnection(configuration)
89
- },
90
- derefTypeCount,
91
- ]
92
- },
93
-
94
- /**
95
- * #action
96
- */
97
- breakConnection(configuration: AnyConfigurationModel) {
98
- const name = readConfObject(configuration, 'name')
99
- const connection = self.connectionInstances.find(c => c.name === name)
100
- if (!connection) {
101
- throw new Error(`no connection found with name ${name}`)
102
- }
103
- self.connectionInstances.remove(connection)
104
- },
105
-
106
- /**
107
- * #action
108
- */
109
- deleteConnection(configuration: AnyConfigurationModel) {
110
- const { jbrowse } = self as typeof self & Instance<BaseRootModelType>
111
- return jbrowse.deleteConnectionConf(configuration)
112
- },
113
-
114
- /**
115
- * #action
116
- */
117
- addConnectionConf(connectionConf: BaseConnectionConfigModel) {
118
- const { jbrowse } = self as typeof self & Instance<BaseRootModelType>
119
- return jbrowse.addConnectionConf(connectionConf)
120
- },
121
-
122
- /**
123
- * #action
124
- */
125
- clearConnections() {
126
- self.connectionInstances.clear()
127
- },
128
- }))
129
- }
130
-
131
- /** Session mixin MST type for a session that has connections */
132
- export type SessionWithConnectionsType = ReturnType<
133
- typeof ConnectionManagementSessionMixin
134
- >
135
-
136
- /** Instance of a session that has connections: `connectionInstances`,
137
- * `makeConnection()`, etc. */
138
- export type SessionWithConnections = Instance<SessionWithConnectionsType>
139
-
140
- /** Type guard for SessionWithConnections */
141
- export function isSessionWithConnections(
142
- session: IAnyStateTreeNode,
143
- ): session is SessionWithConnections {
144
- return isBaseSession(session) && 'connectionInstances' in session
145
- }
@@ -1,63 +0,0 @@
1
- /** MST mixin for managing a queue of dialogs at the level of the session */
2
-
3
- import PluginManager from '@jbrowse/core/PluginManager'
4
- import { DialogComponentType } from '@jbrowse/core/util'
5
- import { IAnyStateTreeNode, Instance, types } from 'mobx-state-tree'
6
- import { isBaseSession } from './BaseSession'
7
-
8
- /**
9
- * #stateModel DialogQueueSessionMixin
10
- */
11
- export function DialogQueueSessionMixin(pluginManager: PluginManager) {
12
- return types
13
- .model('DialogQueueSessionMixin', {})
14
- .volatile(() => ({
15
- queueOfDialogs: [] as [DialogComponentType, unknown][],
16
- }))
17
- .views(self => ({
18
- /**
19
- * #getter
20
- */
21
- get DialogComponent() {
22
- return self.queueOfDialogs[0]?.[0]
23
- },
24
- /**
25
- * #getter
26
- */
27
- get DialogProps() {
28
- return self.queueOfDialogs[0]?.[1]
29
- },
30
- }))
31
- .actions(self => ({
32
- /**
33
- * #action
34
- */
35
- removeActiveDialog() {
36
- self.queueOfDialogs = self.queueOfDialogs.slice(1)
37
- },
38
- /**
39
- * #action
40
- */
41
- queueDialog(
42
- cb: (doneCallback: () => void) => [DialogComponentType, unknown],
43
- ) {
44
- const [component, props] = cb(() => {
45
- this.removeActiveDialog()
46
- })
47
- self.queueOfDialogs = [...self.queueOfDialogs, [component, props]]
48
- },
49
- }))
50
- }
51
-
52
- /** Session mixin MST type for a session that has `queueOfDialogs`, etc. */
53
- export type SessionWithDialogsType = ReturnType<typeof DialogQueueSessionMixin>
54
-
55
- /** Instance of a session that has dialogs */
56
- export type SessionWithDialogs = Instance<SessionWithDialogsType>
57
-
58
- /** Type guard for SessionWithDialogs */
59
- export function isSessionWithDialogs(
60
- session: IAnyStateTreeNode,
61
- ): session is SessionWithDialogs {
62
- return isBaseSession(session) && 'queueOfDialogs' in session
63
- }
@@ -1,222 +0,0 @@
1
- import {
2
- IAnyStateTreeNode,
3
- Instance,
4
- addDisposer,
5
- isAlive,
6
- types,
7
- } from 'mobx-state-tree'
8
-
9
- import PluginManager from '@jbrowse/core/PluginManager'
10
- import { localStorageGetItem, localStorageSetItem } from '@jbrowse/core/util'
11
- import { autorun } from 'mobx'
12
- import {
13
- AnyConfigurationModel,
14
- isConfigurationModel,
15
- } from '@jbrowse/core/configuration'
16
- import { isBaseSession } from './BaseSession'
17
-
18
- const minDrawerWidth = 128
19
-
20
- /**
21
- * #stateModel DrawerWidgetSessionMixin
22
- */
23
- export function DrawerWidgetSessionMixin(pluginManager: PluginManager) {
24
- const widgetStateModelType = pluginManager.pluggableMstType(
25
- 'widget',
26
- 'stateModel',
27
- )
28
- type WidgetStateModel = Instance<typeof widgetStateModelType>
29
- return types
30
- .model({
31
- /**
32
- * #property
33
- */
34
- drawerPosition: types.optional(
35
- types.string,
36
- () => localStorageGetItem('drawerPosition') || 'right',
37
- ),
38
- /**
39
- * #property
40
- */
41
- drawerWidth: types.optional(
42
- types.refinement(types.integer, width => width >= minDrawerWidth),
43
- 384,
44
- ),
45
- /**
46
- * #property
47
- */
48
- widgets: types.map(widgetStateModelType),
49
- /**
50
- * #property
51
- */
52
- activeWidgets: types.map(types.safeReference(widgetStateModelType)),
53
-
54
- /**
55
- * #property
56
- */
57
- minimized: types.optional(types.boolean, false),
58
- })
59
- .views(self => ({
60
- /**
61
- * #getter
62
- */
63
- get visibleWidget() {
64
- if (isAlive(self)) {
65
- // returns most recently added item in active widgets
66
- return [...self.activeWidgets.values()][self.activeWidgets.size - 1]
67
- }
68
- return undefined
69
- },
70
- }))
71
- .actions(self => ({
72
- /**
73
- * #action
74
- */
75
- setDrawerPosition(arg: string) {
76
- self.drawerPosition = arg
77
- localStorage.setItem('drawerPosition', arg)
78
- },
79
-
80
- /**
81
- * #action
82
- */
83
- updateDrawerWidth(drawerWidth: number) {
84
- if (drawerWidth === self.drawerWidth) {
85
- return self.drawerWidth
86
- }
87
- let newDrawerWidth = drawerWidth
88
- if (newDrawerWidth < minDrawerWidth) {
89
- newDrawerWidth = minDrawerWidth
90
- }
91
- self.drawerWidth = newDrawerWidth
92
- return newDrawerWidth
93
- },
94
-
95
- /**
96
- * #action
97
- */
98
- resizeDrawer(distance: number) {
99
- if (self.drawerPosition === 'left') {
100
- distance *= -1
101
- }
102
- const oldDrawerWidth = self.drawerWidth
103
- const newDrawerWidth = this.updateDrawerWidth(oldDrawerWidth - distance)
104
- return oldDrawerWidth - newDrawerWidth
105
- },
106
-
107
- /**
108
- * #action
109
- */
110
- addWidget(
111
- typeName: string,
112
- id: string,
113
- initialState = {},
114
- conf?: unknown,
115
- ) {
116
- const typeDefinition = pluginManager.getElementType('widget', typeName)
117
- if (!typeDefinition) {
118
- throw new Error(`unknown widget type ${typeName}`)
119
- }
120
- const data = {
121
- ...initialState,
122
- id,
123
- type: typeName,
124
- configuration: conf || { type: typeName },
125
- }
126
- self.widgets.set(id, data)
127
- return self.widgets.get(id)
128
- },
129
-
130
- /**
131
- * #action
132
- */
133
- showWidget(widget: WidgetStateModel) {
134
- if (self.activeWidgets.has(widget.id)) {
135
- self.activeWidgets.delete(widget.id)
136
- }
137
- self.activeWidgets.set(widget.id, widget)
138
- self.minimized = false
139
- },
140
-
141
- /**
142
- * #action
143
- */
144
- hasWidget(widget: WidgetStateModel) {
145
- return self.activeWidgets.has(widget.id)
146
- },
147
-
148
- /**
149
- * #action
150
- */
151
- hideWidget(widget: WidgetStateModel) {
152
- self.activeWidgets.delete(widget.id)
153
- },
154
-
155
- /**
156
- * #action
157
- */
158
- minimizeWidgetDrawer() {
159
- self.minimized = true
160
- },
161
- /**
162
- * #action
163
- */
164
- showWidgetDrawer() {
165
- self.minimized = false
166
- },
167
- /**
168
- * #action
169
- */
170
- hideAllWidgets() {
171
- self.activeWidgets.clear()
172
- },
173
-
174
- /**
175
- * #action
176
- * opens a configuration editor to configure the given thing,
177
- * and sets the current task to be configuring it
178
- * @param configuration -
179
- */
180
- editConfiguration(configuration: AnyConfigurationModel) {
181
- if (!isConfigurationModel(configuration)) {
182
- throw new Error(
183
- 'must pass a configuration model to editConfiguration',
184
- )
185
- }
186
- const editor = this.addWidget(
187
- 'ConfigurationEditorWidget',
188
- 'configEditor',
189
- { target: configuration },
190
- )
191
- this.showWidget(editor)
192
- },
193
-
194
- afterAttach() {
195
- addDisposer(
196
- self,
197
- autorun(() => {
198
- localStorageSetItem('drawerPosition', self.drawerPosition)
199
- }),
200
- )
201
- },
202
- }))
203
- }
204
-
205
- /** Session mixin MST type for a session that manages drawer widgets */
206
- export type SessionWithDrawerWidgetsType = ReturnType<
207
- typeof DrawerWidgetSessionMixin
208
- >
209
-
210
- /** Instance of a session that manages drawer widgets */
211
- export type SessionWithDrawerWidgets = Instance<SessionWithDrawerWidgetsType>
212
-
213
- /** Type guard for SessionWithDrawerWidgets */
214
- export function isSessionWithDrawerWidgets(
215
- session: IAnyStateTreeNode,
216
- ): session is SessionWithDrawerWidgets {
217
- return (
218
- isBaseSession(session) &&
219
- 'widgets' in session &&
220
- 'drawerPosition' in session
221
- )
222
- }
@@ -1,151 +0,0 @@
1
- import {
2
- IAnyStateTreeNode,
3
- Instance,
4
- getSnapshot,
5
- types,
6
- } from 'mobx-state-tree'
7
-
8
- import PluginManager from '@jbrowse/core/PluginManager'
9
- import { readConfObject } from '@jbrowse/core/configuration'
10
- import { Region } from '@jbrowse/core/util'
11
- import { DrawerWidgetSessionMixin } from './DrawerWidgets'
12
- import { IBaseViewModel } from '@jbrowse/core/pluggableElementTypes'
13
- import { IBaseViewModelWithDisplayedRegions } from '@jbrowse/core/pluggableElementTypes/models/BaseViewModel'
14
-
15
- // locals
16
- import { BaseSessionModel, isBaseSession } from './BaseSession'
17
-
18
- /**
19
- * #stateModel MultipleViewsSessionMixin
20
- */
21
- export function MultipleViewsSessionMixin(pluginManager: PluginManager) {
22
- return types
23
- .compose(
24
- BaseSessionModel(pluginManager),
25
- DrawerWidgetSessionMixin(pluginManager),
26
- )
27
- .props({
28
- /**
29
- * #property
30
- */
31
- views: types.array(pluginManager.pluggableMstType('view', 'stateModel')),
32
- })
33
- .actions(self => ({
34
- /**
35
- * #action
36
- */
37
- moveViewUp(id: string) {
38
- const idx = self.views.findIndex(v => v.id === id)
39
-
40
- if (idx === -1) {
41
- return
42
- }
43
- if (idx > 0) {
44
- self.views.splice(idx - 1, 2, self.views[idx], self.views[idx - 1])
45
- }
46
- },
47
- /**
48
- * #action
49
- */
50
- moveViewDown(id: string) {
51
- const idx = self.views.findIndex(v => v.id === id)
52
-
53
- if (idx === -1) {
54
- return
55
- }
56
-
57
- if (idx < self.views.length - 1) {
58
- self.views.splice(idx, 2, self.views[idx + 1], self.views[idx])
59
- }
60
- },
61
-
62
- /**
63
- * #action
64
- */
65
- addView(typeName: string, initialState = {}) {
66
- const typeDefinition = pluginManager.getElementType('view', typeName)
67
- if (!typeDefinition) {
68
- throw new Error(`unknown view type ${typeName}`)
69
- }
70
-
71
- const length = self.views.push({
72
- ...initialState,
73
- type: typeName,
74
- })
75
- return self.views[length - 1]
76
- },
77
-
78
- /**
79
- * #action
80
- */
81
- removeView(view: IBaseViewModel) {
82
- for (const [, widget] of self.activeWidgets) {
83
- if (widget.view && widget.view.id === view.id) {
84
- self.hideWidget(widget)
85
- }
86
- }
87
- self.views.remove(view)
88
- },
89
-
90
- /**
91
- * #action
92
- */
93
- addLinearGenomeViewOfAssembly(assemblyName: string, initialState = {}) {
94
- return this.addViewOfAssembly(
95
- 'LinearGenomeView',
96
- assemblyName,
97
- initialState,
98
- )
99
- },
100
-
101
- /**
102
- * #action
103
- */
104
- addViewOfAssembly(
105
- viewType: string,
106
- assemblyName: string,
107
- initialState: Record<string, unknown> = {},
108
- ) {
109
- const asm = self.assemblies.find(
110
- s => readConfObject(s, 'name') === assemblyName,
111
- )
112
- if (!asm) {
113
- throw new Error(
114
- `Could not add view of assembly "${assemblyName}", assembly name not found`,
115
- )
116
- }
117
- return this.addView(viewType, {
118
- ...initialState,
119
- displayRegionsFromAssemblyName: readConfObject(asm, 'name'),
120
- })
121
- },
122
-
123
- /**
124
- * #action
125
- */
126
- addViewFromAnotherView(
127
- viewType: string,
128
- otherView: IBaseViewModelWithDisplayedRegions,
129
- initialState: { displayedRegions?: Region[] } = {},
130
- ) {
131
- const state = { ...initialState }
132
- state.displayedRegions = getSnapshot(otherView.displayedRegions)
133
- return this.addView(viewType, state)
134
- },
135
- }))
136
- }
137
-
138
- /** Session mixin MST type for a session that manages multiple views */
139
- export type SessionWithMultipleViewsType = ReturnType<
140
- typeof MultipleViewsSessionMixin
141
- >
142
-
143
- /** Instance of a session with multiple views */
144
- export type SessionWithMultipleViews = Instance<SessionWithMultipleViewsType>
145
-
146
- /** Type guard for SessionWithMultipleViews */
147
- export function isSessionWithMultipleViews(
148
- session: IAnyStateTreeNode,
149
- ): session is SessionWithMultipleViews {
150
- return isBaseSession(session) && 'views' in session
151
- }
@@ -1,134 +0,0 @@
1
- /** MST props, views, actions, etc related to managing connections */
2
-
3
- import PluginManager from '@jbrowse/core/PluginManager'
4
- import {
5
- TrackViewModel,
6
- getContainingView,
7
- isSessionModelWithWidgets,
8
- } from '@jbrowse/core/util'
9
- import {
10
- IAnyStateTreeNode,
11
- Instance,
12
- getMembers,
13
- getParent,
14
- getSnapshot,
15
- getType,
16
- isModelType,
17
- isReferenceType,
18
- types,
19
- walk,
20
- } from 'mobx-state-tree'
21
-
22
- import type { BaseTrackConfig } from '@jbrowse/core/pluggableElementTypes'
23
- // locals
24
- import { isBaseSession } from './BaseSession'
25
-
26
- export interface ReferringNode {
27
- node: IAnyStateTreeNode
28
- key: string
29
- }
30
-
31
- /**
32
- * #stateModel ReferenceManagementSessionMixin
33
- */
34
- export function ReferenceManagementSessionMixin(pluginManager: PluginManager) {
35
- return types
36
- .model('ReferenceManagementSessionMixin', {})
37
- .views(self => ({
38
- /**
39
- * #method
40
- * See if any MST nodes currently have a types.reference to this object.
41
- *
42
- * @param object - object
43
- * @returns An array where the first element is the node referring
44
- * to the object and the second element is they property name the node is
45
- * using to refer to the object
46
- */
47
- getReferring(object: IAnyStateTreeNode) {
48
- const refs: ReferringNode[] = []
49
- walk(getParent(self), node => {
50
- if (isModelType(getType(node))) {
51
- const members = getMembers(node)
52
- Object.entries(members.properties).forEach(([key, value]) => {
53
- if (isReferenceType(value) && node[key] === object) {
54
- refs.push({ node, key })
55
- }
56
- })
57
- }
58
- })
59
- return refs
60
- },
61
- }))
62
- .actions(self => ({
63
- /**
64
- * #action
65
- */
66
- removeReferring(
67
- referring: ReferringNode[],
68
- track: BaseTrackConfig,
69
- callbacks: Function[],
70
- dereferenceTypeCount: Record<string, number>,
71
- ) {
72
- referring.forEach(({ node }) => {
73
- let dereferenced = false
74
- try {
75
- // If a view is referring to the track config, remove the track
76
- // from the view
77
- const type = 'open track(s)'
78
- const view = getContainingView(node) as TrackViewModel
79
- callbacks.push(() => view.hideTrack(track.trackId))
80
- dereferenced = true
81
- if (!dereferenceTypeCount[type]) {
82
- dereferenceTypeCount[type] = 0
83
- }
84
- dereferenceTypeCount[type] += 1
85
- } catch (err1) {
86
- // ignore
87
- }
88
-
89
- if (isSessionModelWithWidgets(self) && self.widgets.has(node.id)) {
90
- // If a configuration editor widget has the track config
91
- // open, close the widget
92
- const type = 'configuration editor widget(s)'
93
- if (isSessionModelWithWidgets(self)) {
94
- callbacks.push(() => self.hideWidget(node))
95
- }
96
- dereferenced = true
97
- if (!dereferenceTypeCount[type]) {
98
- dereferenceTypeCount[type] = 0
99
- }
100
- dereferenceTypeCount[type] += 1
101
- }
102
- if (!dereferenced) {
103
- throw new Error(
104
- `Error when closing this connection, the following node is still referring to a track configuration: ${JSON.stringify(
105
- getSnapshot(node),
106
- )}`,
107
- )
108
- }
109
- })
110
- },
111
- }))
112
- }
113
-
114
- /** Session mixin MST type for a session that manages multiple views */
115
- export type SessionWithReferenceManagementType = ReturnType<
116
- typeof ReferenceManagementSessionMixin
117
- >
118
-
119
- /** Instance of a session with MST reference management (`getReferring()`, `removeReferring()`) */
120
- export type SessionWithReferenceManagement =
121
- Instance<SessionWithReferenceManagementType>
122
-
123
- /** Type guard for SessionWithReferenceManagement */
124
- export function isSessionWithReferenceManagement(
125
- thing: IAnyStateTreeNode,
126
- ): thing is SessionWithReferenceManagement {
127
- return (
128
- isBaseSession(thing) &&
129
- 'getReferring' in thing &&
130
- typeof thing.getReferring === 'function' &&
131
- 'removeReferring' in thing &&
132
- typeof thing.removeReferring === 'function'
133
- )
134
- }