@jbrowse/product-core 4.3.0 → 5.0.0-beta.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/esm/RootModel/BaseRootModel.d.ts +514 -323
- package/esm/RootModel/BaseRootModel.js +141 -14
- package/esm/RootModel/HierarchicalConfig.d.ts +30 -20
- package/esm/RootModel/HierarchicalConfig.js +36 -0
- package/esm/RootModel/InternetAccounts.d.ts +18 -1
- package/esm/RootModel/InternetAccounts.js +120 -22
- package/esm/RootModel/PreferencesConfig.d.ts +37 -0
- package/esm/RootModel/PreferencesConfig.js +75 -0
- package/esm/RootModel/createConfigModel.d.ts +257 -0
- package/esm/RootModel/createConfigModel.js +77 -0
- package/esm/RootModel/index.d.ts +10 -5
- package/esm/RootModel/index.js +10 -5
- package/esm/RootModel/menuItems.d.ts +24 -0
- package/esm/RootModel/menuItems.js +141 -0
- package/esm/Session/BaseSession.d.ts +285 -11
- package/esm/Session/BaseSession.js +383 -15
- package/esm/Session/Connections.d.ts +115 -8
- package/esm/Session/Connections.js +196 -74
- package/esm/Session/DrawerWidgets.d.ts +145 -13
- package/esm/Session/DrawerWidgets.js +219 -49
- package/esm/Session/MultipleViews.d.ts +1067 -1177
- package/esm/Session/MultipleViews.js +395 -64
- package/esm/Session/Preferences.d.ts +1389 -0
- package/esm/Session/Preferences.js +58 -0
- package/esm/Session/ReferenceManagement.d.ts +28 -3
- package/esm/Session/ReferenceManagement.js +56 -41
- package/esm/Session/SessionTracks.d.ts +1101 -1180
- package/esm/Session/SessionTracks.js +584 -34
- package/esm/Session/Themes.d.ts +136 -2
- package/esm/Session/Themes.js +267 -21
- package/esm/Session/TrackMenu.d.ts +88 -0
- package/esm/Session/TrackMenu.js +175 -0
- package/esm/Session/TrackMenuSessionMixin.d.ts +27 -0
- package/esm/Session/TrackMenuSessionMixin.js +42 -0
- package/esm/Session/Tracks.d.ts +945 -1159
- package/esm/Session/Tracks.js +229 -30
- package/esm/Session/assertSessionModel.d.ts +21 -0
- package/esm/Session/assertSessionModel.js +1 -0
- package/esm/Session/copyTrackSnapshot.d.ts +21 -0
- package/esm/Session/copyTrackSnapshot.js +20 -0
- package/esm/Session/developerMode.d.ts +7 -0
- package/esm/Session/developerMode.js +43 -0
- package/esm/Session/finalizeSession.d.ts +15 -0
- package/esm/Session/finalizeSession.js +28 -0
- package/esm/Session/hydratedForms.d.ts +16 -0
- package/esm/Session/hydratedForms.js +13 -0
- package/esm/Session/index.d.ts +27 -10
- package/esm/Session/index.js +16 -10
- package/esm/Session/pluginExtraTrackItems.d.ts +11 -0
- package/esm/Session/pluginExtraTrackItems.js +13 -0
- package/esm/Session/readdedTrackConf.d.ts +8 -0
- package/esm/Session/readdedTrackConf.js +24 -0
- package/esm/Session/shareableSnapshot.d.ts +23 -0
- package/esm/Session/shareableSnapshot.js +66 -0
- package/esm/Session/temporaryAssemblyTracks.d.ts +24 -0
- package/esm/Session/temporaryAssemblyTracks.js +37 -0
- package/esm/assertExtends.d.ts +55 -0
- package/esm/assertExtends.js +1 -0
- package/esm/controllerTracks.d.ts +76 -0
- package/esm/controllerTracks.js +125 -0
- package/esm/destroyViewState.d.ts +21 -0
- package/esm/destroyViewState.js +29 -0
- package/esm/embeddedController.d.ts +57 -0
- package/esm/embeddedController.js +100 -0
- package/esm/index.d.ts +32 -4
- package/esm/index.js +31 -4
- package/esm/loadPlugins.d.ts +38 -0
- package/esm/loadPlugins.js +45 -0
- package/esm/localFiles.d.ts +74 -0
- package/esm/localFiles.js +156 -0
- package/esm/observeSession.d.ts +55 -0
- package/esm/observeSession.js +90 -0
- package/esm/parallelChunkLoading.d.ts +30 -0
- package/esm/parallelChunkLoading.js +71 -0
- package/esm/pluginInput.d.ts +32 -0
- package/esm/pluginInput.js +19 -0
- package/esm/pruneUnbuildableNodes.d.ts +109 -0
- package/esm/pruneUnbuildableNodes.js +562 -0
- package/esm/resolveAssemblies.d.ts +68 -0
- package/esm/resolveAssemblies.js +77 -0
- package/esm/rpcWorker.d.ts +36 -4
- package/esm/rpcWorker.js +126 -20
- package/esm/sessionMigrations/index.d.ts +15 -0
- package/esm/sessionMigrations/index.js +178 -0
- package/esm/sessionUrl.d.ts +40 -0
- package/esm/sessionUrl.js +66 -0
- package/esm/sessionUtils.d.ts +74 -0
- package/esm/sessionUtils.js +599 -0
- package/esm/siblingCast.d.ts +14 -0
- package/esm/siblingCast.js +16 -0
- package/esm/snapshotUtils.d.ts +8 -0
- package/esm/snapshotUtils.js +12 -0
- package/esm/ui/AboutDialog.d.ts +8 -3
- package/esm/ui/AboutDialog.js +14 -5
- package/esm/ui/AboutDialogContents.d.ts +2 -6
- package/esm/ui/AboutDialogContents.js +13 -17
- package/esm/ui/AssemblyInfoPanel.d.ts +5 -0
- package/esm/ui/AssemblyInfoPanel.js +63 -0
- package/esm/ui/DescriptionPanel.d.ts +3 -0
- package/esm/ui/DescriptionPanel.js +25 -0
- package/esm/ui/Drawer.d.ts +21 -0
- package/esm/ui/Drawer.js +60 -0
- package/esm/ui/DrawerControls.d.ts +5 -0
- package/esm/ui/DrawerControls.js +28 -0
- package/esm/ui/DrawerHeader.d.ts +6 -0
- package/esm/ui/DrawerHeader.js +36 -0
- package/esm/ui/DrawerWidget.d.ts +5 -0
- package/esm/ui/DrawerWidget.js +12 -0
- package/esm/ui/DrawerWidgetSelector.d.ts +5 -0
- package/esm/ui/DrawerWidgetSelector.js +40 -0
- package/esm/ui/FileInfoPanel.d.ts +3 -6
- package/esm/ui/FileInfoPanel.js +36 -26
- package/esm/ui/GeneralPreferencesTab.d.ts +17 -0
- package/esm/ui/GeneralPreferencesTab.js +34 -0
- package/esm/ui/HeaderButtons.d.ts +2 -1
- package/esm/ui/HeaderButtons.js +15 -17
- package/esm/ui/ModalWidget.d.ts +13 -0
- package/esm/ui/ModalWidget.js +48 -0
- package/esm/ui/ModalWidgetAppBar.d.ts +8 -0
- package/esm/ui/ModalWidgetAppBar.js +9 -0
- package/esm/ui/PreferenceCheckbox.d.ts +6 -0
- package/esm/ui/PreferenceCheckbox.js +16 -0
- package/esm/ui/PreferencesDialog.d.ts +34 -0
- package/esm/ui/PreferencesDialog.js +55 -0
- package/esm/ui/PreferencesResetDialog.d.ts +8 -0
- package/esm/ui/PreferencesResetDialog.js +19 -0
- package/esm/ui/RefNameAliasesDialog.d.ts +9 -0
- package/esm/ui/RefNameAliasesDialog.js +65 -0
- package/esm/ui/RefNameInfoDialog.d.ts +3 -6
- package/esm/ui/RefNameInfoDialog.js +45 -63
- package/esm/ui/ViewPreferencesTab.d.ts +12 -0
- package/esm/ui/ViewPreferencesTab.js +15 -0
- package/esm/ui/WidgetBody.d.ts +18 -0
- package/esm/ui/WidgetBody.js +22 -0
- package/esm/ui/WidgetHeading.d.ts +7 -0
- package/esm/ui/WidgetHeading.js +7 -0
- package/esm/ui/aboutTestUtils.d.ts +140 -0
- package/esm/ui/aboutTestUtils.js +25 -0
- package/esm/ui/descriptionHtml.d.ts +25 -0
- package/esm/ui/descriptionHtml.js +64 -0
- package/esm/ui/drawerLayout.d.ts +18 -0
- package/esm/ui/drawerLayout.js +22 -0
- package/esm/ui/index.d.ts +15 -1
- package/esm/ui/index.js +13 -1
- package/esm/ui/preferencesReset.d.ts +18 -0
- package/esm/ui/preferencesReset.js +69 -0
- package/esm/ui/util.d.ts +22 -7
- package/esm/ui/util.js +19 -41
- package/esm/useEngineLifecycle.d.ts +19 -0
- package/esm/useEngineLifecycle.js +44 -0
- package/package.json +15 -18
- package/esm/RootModel/FormatAbout.d.ts +0 -12
- package/esm/RootModel/FormatAbout.js +0 -15
- package/esm/RootModel/FormatDetails.d.ts +0 -24
- package/esm/RootModel/FormatDetails.js +0 -27
- package/esm/Session/DialogQueue.d.ts +0 -17
- package/esm/Session/DialogQueue.js +0 -31
|
@@ -1,68 +1,436 @@
|
|
|
1
|
+
import { readConfObject } from '@jbrowse/core/configuration';
|
|
2
|
+
import SnackbarModel from '@jbrowse/core/ui/SnackbarModel';
|
|
3
|
+
import { setNumberGrouping } from '@jbrowse/core/util';
|
|
4
|
+
import { freezeDeep } from '@jbrowse/core/util/freezeDeep';
|
|
5
|
+
import { isSameHighlight } from '@jbrowse/core/util/highlights';
|
|
6
|
+
import { isFeature, unwrapFeature } from '@jbrowse/core/util/simpleFeature';
|
|
1
7
|
import { ElementId } from '@jbrowse/core/util/types/mst';
|
|
2
|
-
import { getParent, isStateTreeNode, types } from '@jbrowse/mobx-state-tree';
|
|
8
|
+
import { cast, getParent, isStateTreeNode, types, } from '@jbrowse/mobx-state-tree';
|
|
9
|
+
import { observable } from 'mobx';
|
|
10
|
+
import { applyDeveloperMode } from './developerMode.js';
|
|
11
|
+
function isAnimationMode(val) {
|
|
12
|
+
return val === 'system' || val === 'enabled' || val === 'disabled';
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* #stateModel BaseSessionModel
|
|
16
|
+
*
|
|
17
|
+
* base session shared by all JBrowse products. Be careful what you include
|
|
18
|
+
* here, everything will use it.
|
|
19
|
+
*/
|
|
3
20
|
export function BaseSessionModel(_pluginManager) {
|
|
4
|
-
|
|
21
|
+
const baseModel = types
|
|
5
22
|
.model({
|
|
23
|
+
/**
|
|
24
|
+
* #property
|
|
25
|
+
*/
|
|
6
26
|
id: ElementId,
|
|
27
|
+
/**
|
|
28
|
+
* #property
|
|
29
|
+
*/
|
|
7
30
|
name: types.string,
|
|
8
|
-
|
|
31
|
+
/**
|
|
32
|
+
* #property
|
|
33
|
+
* used to keep track of which view is in focus
|
|
34
|
+
*/
|
|
35
|
+
focusedViewId: types.maybe(types.string),
|
|
36
|
+
/**
|
|
37
|
+
* #property
|
|
38
|
+
* translucent bands over genomic regions; every view draws the ones on
|
|
39
|
+
* its own assemblies
|
|
40
|
+
*/
|
|
41
|
+
highlights: types.stripDefault(types.array(types.frozen()), []),
|
|
42
|
+
/**
|
|
43
|
+
* #property
|
|
44
|
+
*/
|
|
45
|
+
highlightsVisible: types.stripDefault(types.boolean, true),
|
|
46
|
+
/**
|
|
47
|
+
* #property
|
|
48
|
+
* whether a band's label is written on it
|
|
49
|
+
*/
|
|
50
|
+
highlightLabelsVisible: types.stripDefault(types.boolean, true),
|
|
51
|
+
/**
|
|
52
|
+
* #property
|
|
53
|
+
* views, tracks, displays and widgets `pruneUnbuildableNodes` took out of
|
|
54
|
+
* the tree because this build has no plugin for their type, each with the
|
|
55
|
+
* anchor that puts it back. Nothing in the session reads its contents,
|
|
56
|
+
* and `pruneUnbuildableNodes` defines their structure.
|
|
57
|
+
*
|
|
58
|
+
* It is a **declared property** because MST drops undeclared snapshot
|
|
59
|
+
* keys without error. Without this declaration the held nodes survive
|
|
60
|
+
* the prune and are then discarded when `setSession` builds the tree,
|
|
61
|
+
* while every unit test of the prune still passes.
|
|
62
|
+
* `heldNodesSurviveTheSession.test.ts` tests that they survive.
|
|
63
|
+
*/
|
|
64
|
+
heldForMissingPlugins: types.stripDefault(types.frozen(), undefined),
|
|
9
65
|
})
|
|
10
66
|
.volatile(() => ({
|
|
67
|
+
/**
|
|
68
|
+
* #volatile
|
|
69
|
+
* this is the globally "selected" object. can be anything. code that
|
|
70
|
+
* wants to deal with this should examine it to see what kind of thing it
|
|
71
|
+
* is.
|
|
72
|
+
*/
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
11
74
|
selection: undefined,
|
|
75
|
+
/**
|
|
76
|
+
* #volatile
|
|
77
|
+
* this is the globally "hovered" object. can be anything. code that
|
|
78
|
+
* wants to deal with this should examine it to see what kind of thing it
|
|
79
|
+
* is.
|
|
80
|
+
*/
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
12
82
|
hovered: undefined,
|
|
83
|
+
/**
|
|
84
|
+
* #volatile
|
|
85
|
+
*/
|
|
86
|
+
queueOfDialogs: [],
|
|
87
|
+
/**
|
|
88
|
+
* #volatile
|
|
89
|
+
* runtime user-preference overrides keyed by preference id, resolved by
|
|
90
|
+
* `getPreference` against the `configuration.preferences` admin defaults.
|
|
91
|
+
* Empty here (config-only); products that let users edit preferences load
|
|
92
|
+
* and persist these via localStorage. A runtime override map layered over
|
|
93
|
+
* config defaults, kept off the snapshot since prefs are local UI.
|
|
94
|
+
*
|
|
95
|
+
* An `observable.map` (not a plain object reassigned wholesale) so each
|
|
96
|
+
* preference is its own tracked key: writing one (`setScrollZoom`) can't
|
|
97
|
+
* invalidate a reader of another. A single spread-replaced object made
|
|
98
|
+
* every setter wake every reader, so toggling scroll-to-zoom re-fetched
|
|
99
|
+
* every track.
|
|
100
|
+
*
|
|
101
|
+
* `deep: false` keeps an object-valued preference a plain object rather
|
|
102
|
+
* than a MobX Proxy, which V8's structured-clone serializer rejects. The
|
|
103
|
+
* map still notifies per key on `set`, so shallow values lose no
|
|
104
|
+
* reactivity — and nothing can mutate a preference in place, because
|
|
105
|
+
* `setPreferenceOverride` freezes what it stores.
|
|
106
|
+
*/
|
|
107
|
+
preferencesOverrides: observable.map(undefined, {
|
|
108
|
+
deep: false,
|
|
109
|
+
}),
|
|
13
110
|
}))
|
|
14
111
|
.views(self => ({
|
|
112
|
+
/**
|
|
113
|
+
* #getter
|
|
114
|
+
*/
|
|
15
115
|
get root() {
|
|
16
116
|
return getParent(self);
|
|
17
117
|
},
|
|
18
118
|
}))
|
|
19
119
|
.views(self => ({
|
|
120
|
+
/**
|
|
121
|
+
* #getter
|
|
122
|
+
*/
|
|
20
123
|
get jbrowse() {
|
|
21
124
|
return self.root.jbrowse;
|
|
22
125
|
},
|
|
126
|
+
/**
|
|
127
|
+
* #getter
|
|
128
|
+
*/
|
|
23
129
|
get rpcManager() {
|
|
24
130
|
return self.root.rpcManager;
|
|
25
131
|
},
|
|
132
|
+
/**
|
|
133
|
+
* #getter
|
|
134
|
+
*/
|
|
26
135
|
get configuration() {
|
|
27
136
|
return this.jbrowse.configuration;
|
|
28
137
|
},
|
|
138
|
+
/**
|
|
139
|
+
* #getter
|
|
140
|
+
*/
|
|
29
141
|
get adminMode() {
|
|
30
142
|
return self.root.adminMode;
|
|
31
143
|
},
|
|
144
|
+
/**
|
|
145
|
+
* #getter
|
|
146
|
+
*/
|
|
32
147
|
get textSearchManager() {
|
|
33
148
|
return self.root.textSearchManager;
|
|
34
149
|
},
|
|
35
150
|
}))
|
|
36
151
|
.views(self => ({
|
|
152
|
+
/**
|
|
153
|
+
* #getter
|
|
154
|
+
*/
|
|
37
155
|
get assemblies() {
|
|
38
156
|
return self.jbrowse.assemblies;
|
|
39
157
|
},
|
|
158
|
+
/**
|
|
159
|
+
* #getter
|
|
160
|
+
*/
|
|
161
|
+
get DialogComponent() {
|
|
162
|
+
return self.queueOfDialogs[0]?.[0];
|
|
163
|
+
},
|
|
164
|
+
/**
|
|
165
|
+
* #getter
|
|
166
|
+
*/
|
|
167
|
+
get DialogProps() {
|
|
168
|
+
return self.queueOfDialogs[0]?.[1];
|
|
169
|
+
},
|
|
170
|
+
}))
|
|
171
|
+
.views(self => ({
|
|
172
|
+
/**
|
|
173
|
+
* #method
|
|
174
|
+
* the admin/embedder `configuration.preferences` value for a key, ignoring
|
|
175
|
+
* any runtime override — i.e. what a reset falls back to. Exposed rather
|
|
176
|
+
* than inlined because "differs from the default" is a question the
|
|
177
|
+
* Preferences reset diff asks about settings this map doesn't hold (see
|
|
178
|
+
* `defaultUseWorkspaces`).
|
|
179
|
+
*/
|
|
180
|
+
getPreferenceDefault(key) {
|
|
181
|
+
const { preferences } = self.configuration;
|
|
182
|
+
return preferences ? readConfObject(preferences, key) : undefined;
|
|
183
|
+
},
|
|
184
|
+
/**
|
|
185
|
+
* #method
|
|
186
|
+
* resolved value of a user preference: a runtime override if the user set
|
|
187
|
+
* one, otherwise the admin/embedder `configuration.preferences` default.
|
|
188
|
+
* The override map is empty unless the product loads it (web/desktop).
|
|
189
|
+
*/
|
|
190
|
+
getPreference(key) {
|
|
191
|
+
const override = self.preferencesOverrides.get(key);
|
|
192
|
+
return override === undefined
|
|
193
|
+
? this.getPreferenceDefault(key)
|
|
194
|
+
: override;
|
|
195
|
+
},
|
|
196
|
+
/**
|
|
197
|
+
* #method
|
|
198
|
+
* every scalar preference override that currently differs from its
|
|
199
|
+
* config/admin default, as `{ path, from, to }` rows whose path is the
|
|
200
|
+
* override's own key. A scalar pref (animationMode, scrollZoom) whose
|
|
201
|
+
* override equals the default is omitted, since reverting it is a no-op.
|
|
202
|
+
*/
|
|
203
|
+
getPreferenceChanges() {
|
|
204
|
+
const changes = [];
|
|
205
|
+
for (const [key, value] of self.preferencesOverrides.entries()) {
|
|
206
|
+
const dflt = this.getPreferenceDefault(key);
|
|
207
|
+
if (value !== dflt) {
|
|
208
|
+
changes.push({
|
|
209
|
+
path: [key],
|
|
210
|
+
from: dflt,
|
|
211
|
+
to: value,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return changes;
|
|
216
|
+
},
|
|
217
|
+
}))
|
|
218
|
+
.views(self => ({
|
|
219
|
+
/**
|
|
220
|
+
* #getter
|
|
221
|
+
* resolved feature-layout animation mode (never undefined)
|
|
222
|
+
*/
|
|
223
|
+
get animationMode() {
|
|
224
|
+
const mode = self.getPreference('animationMode');
|
|
225
|
+
return isAnimationMode(mode) ? mode : 'enabled';
|
|
226
|
+
},
|
|
227
|
+
/**
|
|
228
|
+
* #getter
|
|
229
|
+
* resolved scroll-to-zoom preference. Global and personal (never shared in
|
|
230
|
+
* a session snapshot); every wheel-zoom view reads this single value.
|
|
231
|
+
*/
|
|
232
|
+
get scrollZoom() {
|
|
233
|
+
return self.getPreference('scrollZoom') === true;
|
|
234
|
+
},
|
|
235
|
+
/**
|
|
236
|
+
* #getter
|
|
237
|
+
* resolved thousand-separator preference. Read for display in the
|
|
238
|
+
* Preferences dialog; the formatter itself reads a plain module variable
|
|
239
|
+
* set at startup in each realm (see `setNumberGrouping`), because worker-
|
|
240
|
+
* built strings can't see a main-thread observable.
|
|
241
|
+
*/
|
|
242
|
+
get numberGrouping() {
|
|
243
|
+
return self.getPreference('numberGrouping') !== false;
|
|
244
|
+
},
|
|
40
245
|
}))
|
|
41
246
|
.actions(self => ({
|
|
247
|
+
afterAttach() {
|
|
248
|
+
// push the admin/embedder default down to the formatter, which is a
|
|
249
|
+
// plain module variable rather than an observable (see
|
|
250
|
+
// `setNumberGrouping`). Embedded products stop here; web and desktop
|
|
251
|
+
// compose PreferencesSessionMixin, whose own afterAttach runs after
|
|
252
|
+
// this one and re-applies the value once the user's stored overrides
|
|
253
|
+
// are loaded, so a user override still wins over the config default.
|
|
254
|
+
setNumberGrouping(self.numberGrouping);
|
|
255
|
+
},
|
|
256
|
+
/**
|
|
257
|
+
* #action
|
|
258
|
+
* set the global selection, i.e. the globally-selected object. can be a
|
|
259
|
+
* feature, a view, just about anything
|
|
260
|
+
*
|
|
261
|
+
* A feature is unwrapped on the way in, so app state never holds a
|
|
262
|
+
* jexlFeatureProxy. `isFeature` accepts a proxy, but on one `id` is a
|
|
263
|
+
* data field rather than the method the Feature type promises — every
|
|
264
|
+
* consumer doing `isFeature(selection) ? selection.id() : …` would throw.
|
|
265
|
+
*/
|
|
42
266
|
setSelection(thing) {
|
|
43
|
-
self.selection = thing;
|
|
267
|
+
self.selection = isFeature(thing) ? unwrapFeature(thing) : thing;
|
|
44
268
|
},
|
|
269
|
+
/**
|
|
270
|
+
* #action
|
|
271
|
+
* clears the global selection
|
|
272
|
+
*/
|
|
45
273
|
clearSelection() {
|
|
46
274
|
self.selection = undefined;
|
|
47
275
|
},
|
|
276
|
+
/**
|
|
277
|
+
* #action
|
|
278
|
+
*/
|
|
48
279
|
setHovered(thing) {
|
|
49
280
|
self.hovered = thing;
|
|
50
281
|
},
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
282
|
+
/**
|
|
283
|
+
* #action
|
|
284
|
+
*/
|
|
285
|
+
setHighlightsVisible(arg) {
|
|
286
|
+
self.highlightsVisible = arg;
|
|
287
|
+
},
|
|
288
|
+
/**
|
|
289
|
+
* #action
|
|
290
|
+
*/
|
|
291
|
+
setHighlightLabelsVisible(arg) {
|
|
292
|
+
self.highlightLabelsVisible = arg;
|
|
293
|
+
},
|
|
294
|
+
/**
|
|
295
|
+
* #action
|
|
296
|
+
* an identical entry is not added twice, so a spec launched again does not
|
|
297
|
+
* stack its bands. Adding shows the bands again, since a highlight made
|
|
298
|
+
* while they are off would otherwise read as nothing happening
|
|
299
|
+
*/
|
|
300
|
+
addHighlight(highlight) {
|
|
301
|
+
if (!self.highlights.some(h => isSameHighlight(h, highlight))) {
|
|
302
|
+
self.highlights.push(highlight);
|
|
303
|
+
}
|
|
304
|
+
self.highlightsVisible = true;
|
|
305
|
+
},
|
|
306
|
+
/**
|
|
307
|
+
* #action
|
|
308
|
+
*/
|
|
309
|
+
removeHighlight(highlight) {
|
|
310
|
+
self.highlights.remove(highlight);
|
|
311
|
+
},
|
|
312
|
+
/**
|
|
313
|
+
* #action
|
|
314
|
+
*/
|
|
315
|
+
updateHighlight(old, updates) {
|
|
316
|
+
const idx = self.highlights.indexOf(old);
|
|
317
|
+
if (idx !== -1) {
|
|
318
|
+
self.highlights[idx] = { ...old, ...updates };
|
|
319
|
+
self.highlightsVisible = true;
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
/**
|
|
323
|
+
* #action
|
|
324
|
+
*/
|
|
325
|
+
setHighlights(highlights) {
|
|
326
|
+
self.highlights = cast(highlights);
|
|
327
|
+
if (highlights.length) {
|
|
328
|
+
self.highlightsVisible = true;
|
|
329
|
+
}
|
|
330
|
+
},
|
|
331
|
+
/**
|
|
332
|
+
* #action
|
|
333
|
+
* set a runtime user-preference override (see `getPreference`). Mutates
|
|
334
|
+
* volatile state; products persist these to localStorage. An `undefined`
|
|
335
|
+
* value deletes the key (rather than leaving a phantom entry that
|
|
336
|
+
* `getPreference` reads as absent) so the store never holds dead keys.
|
|
337
|
+
*/
|
|
338
|
+
setPreferenceOverride(key, value) {
|
|
339
|
+
if (value === undefined) {
|
|
340
|
+
self.preferencesOverrides.delete(key);
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
// frozen because `deep: false` hands an object-valued preference
|
|
344
|
+
// straight back out by reference, so the "nothing mutates a
|
|
345
|
+
// preference in place" this store relies on is enforced rather than
|
|
346
|
+
// assumed
|
|
347
|
+
self.preferencesOverrides.set(key, freezeDeep(value));
|
|
348
|
+
}
|
|
349
|
+
},
|
|
350
|
+
/**
|
|
351
|
+
* #action
|
|
352
|
+
* clear every runtime preference override at once, so each falls back to
|
|
353
|
+
* its config/admin default. Backs the Preferences dialog "Reset to
|
|
354
|
+
* defaults" button.
|
|
355
|
+
*/
|
|
356
|
+
clearPreferenceOverrides() {
|
|
357
|
+
self.preferencesOverrides.clear();
|
|
358
|
+
},
|
|
359
|
+
/**
|
|
360
|
+
* #action
|
|
361
|
+
* clear a single runtime preference override (see `getPreference`) so it
|
|
362
|
+
* falls back to its config/admin default. Backs the per-entry reset in the
|
|
363
|
+
* Preferences dialog "Reset to defaults" confirmation.
|
|
364
|
+
*/
|
|
365
|
+
clearPreferenceOverride(key) {
|
|
366
|
+
self.preferencesOverrides.delete(key);
|
|
367
|
+
},
|
|
368
|
+
/**
|
|
369
|
+
* #action
|
|
370
|
+
* set the global scroll-to-zoom preference (see the `scrollZoom` getter)
|
|
371
|
+
*/
|
|
372
|
+
setScrollZoom(flag) {
|
|
373
|
+
this.setPreferenceOverride('scrollZoom', flag);
|
|
374
|
+
},
|
|
375
|
+
/**
|
|
376
|
+
* #action
|
|
377
|
+
*/
|
|
378
|
+
setName(str) {
|
|
379
|
+
self.name = str;
|
|
380
|
+
},
|
|
381
|
+
/**
|
|
382
|
+
* #action
|
|
383
|
+
* `undefined` is "no view is focused", which the property has always been
|
|
384
|
+
* able to hold (`types.maybe`) and this had no way to spell. Nothing
|
|
385
|
+
* cleared it on teardown as a result: a view that was focused when it left
|
|
386
|
+
* the session left its id behind, and since every consumer compares
|
|
387
|
+
* `focusedViewId === view.id`, the id matched nothing, the focus ring
|
|
388
|
+
* vanished with nothing to say why, and the dead id persisted into a saved
|
|
389
|
+
* or shared session. `takeOut` clears it now.
|
|
390
|
+
*/
|
|
391
|
+
setFocusedViewId(viewId) {
|
|
392
|
+
self.focusedViewId = viewId;
|
|
393
|
+
},
|
|
394
|
+
/**
|
|
395
|
+
* #action
|
|
396
|
+
*/
|
|
397
|
+
removeActiveDialog() {
|
|
398
|
+
self.queueOfDialogs = self.queueOfDialogs.slice(1);
|
|
399
|
+
},
|
|
400
|
+
/**
|
|
401
|
+
* #action
|
|
402
|
+
*/
|
|
403
|
+
queueDialog(doneCallback) {
|
|
404
|
+
// its own entry, not the head: a late second call must not close the
|
|
405
|
+
// dialog queued behind it
|
|
406
|
+
const entry = doneCallback(() => {
|
|
407
|
+
this.removeDialog(entry);
|
|
408
|
+
});
|
|
409
|
+
self.queueOfDialogs = [...self.queueOfDialogs, entry];
|
|
410
|
+
},
|
|
411
|
+
/**
|
|
412
|
+
* #action
|
|
413
|
+
*/
|
|
414
|
+
removeDialog(entry) {
|
|
415
|
+
self.queueOfDialogs = self.queueOfDialogs.filter(d => d !== entry);
|
|
416
|
+
},
|
|
417
|
+
}));
|
|
418
|
+
return types.compose(baseModel, SnackbarModel()).actions(self => ({
|
|
419
|
+
// after the compose rather than in the afterAttach above, because the
|
|
420
|
+
// notices land in the snackbar this line is the first place to hold both
|
|
421
|
+
// halves of. Web and desktop reach it a second time once the user's stored
|
|
422
|
+
// overrides are loaded (`PreferencesSessionMixin`), and our MST fork
|
|
423
|
+
// auto-chains both hooks.
|
|
424
|
+
afterAttach() {
|
|
425
|
+
applyDeveloperMode(self);
|
|
426
|
+
},
|
|
427
|
+
}));
|
|
62
428
|
}
|
|
429
|
+
/** Type guard for BaseSession */
|
|
63
430
|
export function isBaseSession(thing) {
|
|
64
431
|
return 'id' in thing && 'name' in thing && 'root' in thing;
|
|
65
432
|
}
|
|
433
|
+
/** Type guard for whether a thing is JBrowse session */
|
|
66
434
|
export function isSession(thing) {
|
|
67
435
|
return isStateTreeNode(thing) && isBaseSession(thing);
|
|
68
436
|
}
|
|
@@ -1,21 +1,128 @@
|
|
|
1
1
|
import type PluginManager from '@jbrowse/core/PluginManager';
|
|
2
|
-
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
2
|
+
import type { AnyConfiguration, AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
3
3
|
import type { BaseConnectionConfigModel } from '@jbrowse/core/pluggableElementTypes/models/baseConnectionConfig';
|
|
4
4
|
import type { IAnyStateTreeNode, Instance } from '@jbrowse/mobx-state-tree';
|
|
5
|
+
/**
|
|
6
|
+
* Persisted config of a connection track the user has opened. Keyed by trackId
|
|
7
|
+
* in `connectionTrackConfigs`. `connectionId` records provenance so the track
|
|
8
|
+
* can be grouped under its connection and re-hydrated on demand.
|
|
9
|
+
*/
|
|
10
|
+
export interface ConnectionTrackConfigEntry {
|
|
11
|
+
connectionId: string;
|
|
12
|
+
config: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* #stateModel ConnectionManagementSessionMixin
|
|
16
|
+
*/
|
|
5
17
|
export declare function ConnectionManagementSessionMixin(pluginManager: PluginManager): import("@jbrowse/mobx-state-tree").IModelType<{
|
|
6
|
-
|
|
18
|
+
/**
|
|
19
|
+
* #property
|
|
20
|
+
*/
|
|
21
|
+
connectionInstances: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IAnyType>, [undefined]>;
|
|
22
|
+
/**
|
|
23
|
+
* #property
|
|
24
|
+
* Persisted configs of connection tracks the user has opened, keyed by
|
|
25
|
+
* trackId. Unlike `connectionInstances` (stripped from snapshots, holds
|
|
26
|
+
* the whole fetched hub), this holds only the tracks in use, so an open
|
|
27
|
+
* connection track resolves synchronously on session load without
|
|
28
|
+
* re-establishing the connection.
|
|
29
|
+
*/
|
|
30
|
+
connectionTrackConfigs: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IType<Record<string, ConnectionTrackConfigEntry>, Record<string, ConnectionTrackConfigEntry>, Record<string, ConnectionTrackConfigEntry>>, [undefined]>;
|
|
7
31
|
}, {
|
|
32
|
+
/**
|
|
33
|
+
* #getter
|
|
34
|
+
*/
|
|
8
35
|
readonly connections: BaseConnectionConfigModel[];
|
|
9
36
|
} & {
|
|
10
|
-
|
|
11
|
-
|
|
37
|
+
/**
|
|
38
|
+
* #action
|
|
39
|
+
*/
|
|
40
|
+
makeConnection(configuration: AnyConfigurationModel, initialSnapshot?: object): any;
|
|
41
|
+
/**
|
|
42
|
+
* #action
|
|
43
|
+
* Remove a live connection instance. Tolerant of an already-dormant
|
|
44
|
+
* connection (its instance is stripped from the session on reload).
|
|
45
|
+
* Leaves persisted open-track configs alone — the connect() error path
|
|
46
|
+
* calls this and the user's already-open tracks must survive a transient
|
|
47
|
+
* failure. Full removal goes through `deleteConnection`.
|
|
48
|
+
*/
|
|
12
49
|
breakConnection(configuration: AnyConfigurationModel): void;
|
|
50
|
+
/**
|
|
51
|
+
* #action
|
|
52
|
+
* Close every track a connection contributed — the live instance's
|
|
53
|
+
* tracks plus any persisted open-track configs (a dormant connection,
|
|
54
|
+
* never expanded this session, still renders its opened tracks from
|
|
55
|
+
* `connectionTrackConfigs`) — from all views/widgets, drop the live
|
|
56
|
+
* instance, and drop the persisted configs. The session is left as if the
|
|
57
|
+
* connection had never loaded.
|
|
58
|
+
*/
|
|
59
|
+
teardownConnection(configuration: AnyConfigurationModel): void;
|
|
60
|
+
/**
|
|
61
|
+
* #action
|
|
62
|
+
* Fully remove a connection: tear down its tracks and live instance, then
|
|
63
|
+
* delete its config.
|
|
64
|
+
*/
|
|
13
65
|
deleteConnection(configuration: AnyConfigurationModel): any;
|
|
14
|
-
|
|
66
|
+
/**
|
|
67
|
+
* #action
|
|
68
|
+
* Adds to the **config**, not the session: `jbrowse.connections`, which
|
|
69
|
+
* every visitor to this instance loads. jbrowse-web overrides this so a
|
|
70
|
+
* non-admin's connection lands in `sessionConnections` instead — see
|
|
71
|
+
* WebSessionConnectionsMixin, whose `addSessionConnectionConf` is what
|
|
72
|
+
* to call when you mean the session specifically rather than "wherever
|
|
73
|
+
* this user's edits go".
|
|
74
|
+
*
|
|
75
|
+
* Applications without that override (Desktop, the embedded products)
|
|
76
|
+
* have only this one destination, and it is the right one there: their
|
|
77
|
+
* config and session are saved as a single document.
|
|
78
|
+
*/
|
|
79
|
+
addConnectionConf(connectionConf: AnyConfiguration): any;
|
|
80
|
+
/**
|
|
81
|
+
* #action
|
|
82
|
+
*/
|
|
15
83
|
clearConnections(): void;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
84
|
+
/**
|
|
85
|
+
* #action
|
|
86
|
+
* Snapshot a just-opened connection track's config into
|
|
87
|
+
* `connectionTrackConfigs` so it survives session reload. No-op if the
|
|
88
|
+
* track isn't connection-provided or is already captured (edits go
|
|
89
|
+
* through `updateConnectionTrackConfig`).
|
|
90
|
+
*/
|
|
91
|
+
captureConnectionTrack(trackId: string): void;
|
|
92
|
+
/**
|
|
93
|
+
* #action
|
|
94
|
+
* Persist an edit to an opened connection track. The full config is
|
|
95
|
+
* stored (not a delta): the connection's fetched "base" isn't present at
|
|
96
|
+
* load, so only a complete config resolves synchronously.
|
|
97
|
+
*/
|
|
98
|
+
updateConnectionTrackConfig(trackConf: Record<string, unknown> & {
|
|
99
|
+
trackId: string;
|
|
100
|
+
}): void;
|
|
101
|
+
/**
|
|
102
|
+
* #action
|
|
103
|
+
* Upsert one opened connection track's persisted config.
|
|
104
|
+
*/
|
|
105
|
+
setConnectionTrackConfig(trackId: string, connectionId: string, config: Record<string, unknown>): void;
|
|
106
|
+
/**
|
|
107
|
+
* #action
|
|
108
|
+
* Drop a connection track's persisted config once no open view still
|
|
109
|
+
* references it, so the session doesn't accumulate closed tracks.
|
|
110
|
+
*/
|
|
111
|
+
pruneConnectionTrackConfig(trackId: string): void;
|
|
112
|
+
/**
|
|
113
|
+
* #action
|
|
114
|
+
* Lazily establish a single connection by id if it isn't already live;
|
|
115
|
+
* the track selector calls it when the connection's category is
|
|
116
|
+
* expanded. Fetches without launching a view or showing a success
|
|
117
|
+
* snackbar; already-open tracks keep
|
|
118
|
+
* rendering from `connectionTrackConfigs` meanwhile. Idempotent.
|
|
119
|
+
*/
|
|
120
|
+
hydrateConnection(connectionId: string): void;
|
|
121
|
+
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
|
|
122
|
+
/** Session mixin MST type for a session that has connections */
|
|
19
123
|
export type SessionWithConnectionsType = ReturnType<typeof ConnectionManagementSessionMixin>;
|
|
124
|
+
/** Instance of a session that has connections: `connectionInstances`,
|
|
125
|
+
* `makeConnection()`, etc. */
|
|
20
126
|
export type SessionWithConnections = Instance<SessionWithConnectionsType>;
|
|
127
|
+
/** Type guard for SessionWithConnections */
|
|
21
128
|
export declare function isSessionWithConnections(session: IAnyStateTreeNode): session is SessionWithConnections;
|