@jbrowse/app-core 5.0.0-beta.13 → 5.0.0-beta.14
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/AppSession/AppSessionMixin.d.ts +110 -92
- package/esm/Assemblies/AssembliesMixin.d.ts +30 -0
- package/esm/HistoryManagement/index.d.ts +2 -0
- package/esm/HistoryManagement/index.js +2 -0
- package/esm/JBrowseConfig/RootConfiguration.d.ts +3 -2
- package/esm/JBrowseConfig/RootConfiguration.js +3 -2
- package/esm/JBrowseConfig/index.d.ts +2 -3
- package/esm/JBrowseConfig/index.js +2 -3
- package/esm/JBrowseModel/index.d.ts +9 -1
- package/esm/JBrowseModel/index.js +8 -7
- package/esm/JbApi/jbApi.js +5 -2
- package/esm/RootMenu/index.d.ts +2 -0
- package/esm/RootMenu/index.js +2 -0
- package/esm/SessionSpec/index.d.ts +2 -2
- package/esm/SessionSpec/index.js +1 -1
- package/esm/SessionSpec/parseSessionSpecUrl.d.ts +19 -0
- package/esm/SessionSpec/parseSessionSpecUrl.js +29 -0
- package/esm/WorkspaceLayout/WorkspaceContainer.js +2 -10
- package/esm/WorkspaceLayout/WorkspacePanelActions.js +1 -1
- package/esm/WorkspaceLayout/WorkspaceTab.d.ts +2 -3
- package/esm/WorkspaceLayout/WorkspaceTab.js +2 -2
- package/esm/WorkspaceLayout/model.d.ts +10 -15
- package/esm/WorkspaceLayout/model.js +36 -65
- package/esm/WorkspaceLayout/tree.d.ts +3 -6
- package/esm/WorkspaceLayout/tree.js +8 -12
- package/esm/WorkspaceLayout/useLayoutDrag.js +10 -4
- package/esm/index.d.ts +5 -3
- package/esm/index.js +3 -2
- package/esm/queryParams.d.ts +2 -0
- package/esm/queryParams.js +16 -5
- package/esm/sessionSummary.d.ts +16 -0
- package/esm/sessionSummary.js +57 -0
- package/esm/ui/App/DrawerHeaderHelpDialog.d.ts +3 -2
- package/esm/ui/App/DrawerHeaderHelpDialog.js +4 -2
- package/esm/ui/App/JBrowseTabMenu.d.ts +3 -2
- package/esm/ui/App/JBrowseTabMenu.js +4 -2
- package/esm/ui/App/ThemeModeButton.d.ts +4 -5
- package/esm/ui/App/ThemeModeButton.js +18 -11
- package/esm/ui/App/ViewContainer.js +7 -1
- package/esm/ui/App/ViewMenu.js +34 -25
- package/esm/ui/App/ViewWrapper.js +2 -2
- package/esm/ui/App/viewTitle.d.ts +6 -1
- package/esm/ui/App/viewTitle.js +7 -2
- package/package.json +6 -6
|
@@ -29,6 +29,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
|
|
|
29
29
|
} & {
|
|
30
30
|
defaultValue: unknown;
|
|
31
31
|
};
|
|
32
|
+
readonly circularRefNames: {
|
|
33
|
+
type: "stringArray";
|
|
34
|
+
} & {
|
|
35
|
+
defaultValue: unknown;
|
|
36
|
+
};
|
|
32
37
|
readonly geneticCodesLocation: {
|
|
33
38
|
type: "maybeFileLocation";
|
|
34
39
|
};
|
|
@@ -69,6 +74,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
|
|
|
69
74
|
} & {
|
|
70
75
|
defaultValue: unknown;
|
|
71
76
|
};
|
|
77
|
+
readonly circularRefNames: {
|
|
78
|
+
type: "stringArray";
|
|
79
|
+
} & {
|
|
80
|
+
defaultValue: unknown;
|
|
81
|
+
};
|
|
72
82
|
readonly geneticCodesLocation: {
|
|
73
83
|
type: "maybeFileLocation";
|
|
74
84
|
};
|
|
@@ -128,6 +138,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
|
|
|
128
138
|
} & {
|
|
129
139
|
defaultValue: unknown;
|
|
130
140
|
};
|
|
141
|
+
readonly circularRefNames: {
|
|
142
|
+
type: "stringArray";
|
|
143
|
+
} & {
|
|
144
|
+
defaultValue: unknown;
|
|
145
|
+
};
|
|
131
146
|
readonly geneticCodesLocation: {
|
|
132
147
|
type: "maybeFileLocation";
|
|
133
148
|
};
|
|
@@ -164,6 +179,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
|
|
|
164
179
|
} & {
|
|
165
180
|
defaultValue: unknown;
|
|
166
181
|
};
|
|
182
|
+
readonly circularRefNames: {
|
|
183
|
+
type: "stringArray";
|
|
184
|
+
} & {
|
|
185
|
+
defaultValue: unknown;
|
|
186
|
+
};
|
|
167
187
|
readonly geneticCodesLocation: {
|
|
168
188
|
type: "maybeFileLocation";
|
|
169
189
|
};
|
|
@@ -217,6 +237,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
|
|
|
217
237
|
} & {
|
|
218
238
|
defaultValue: unknown;
|
|
219
239
|
};
|
|
240
|
+
readonly circularRefNames: {
|
|
241
|
+
type: "stringArray";
|
|
242
|
+
} & {
|
|
243
|
+
defaultValue: unknown;
|
|
244
|
+
};
|
|
220
245
|
readonly geneticCodesLocation: {
|
|
221
246
|
type: "maybeFileLocation";
|
|
222
247
|
};
|
|
@@ -253,6 +278,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
|
|
|
253
278
|
} & {
|
|
254
279
|
defaultValue: unknown;
|
|
255
280
|
};
|
|
281
|
+
readonly circularRefNames: {
|
|
282
|
+
type: "stringArray";
|
|
283
|
+
} & {
|
|
284
|
+
defaultValue: unknown;
|
|
285
|
+
};
|
|
256
286
|
readonly geneticCodesLocation: {
|
|
257
287
|
type: "maybeFileLocation";
|
|
258
288
|
};
|
|
@@ -3,6 +3,8 @@ export declare function historyShortcut(e: ShortcutKeys): "redo" | "undo" | unde
|
|
|
3
3
|
/**
|
|
4
4
|
* #stateModel HistoryManagementMixin
|
|
5
5
|
* #category root
|
|
6
|
+
* Adds undo and redo of session changes to the root model, bound to Ctrl+Z
|
|
7
|
+
* and Ctrl+Y (Cmd on macOS).
|
|
6
8
|
*/
|
|
7
9
|
export declare function HistoryManagementMixin(): import("@jbrowse/mobx-state-tree").IModelType<{
|
|
8
10
|
/**
|
|
@@ -28,6 +28,8 @@ export function historyShortcut(e) {
|
|
|
28
28
|
/**
|
|
29
29
|
* #stateModel HistoryManagementMixin
|
|
30
30
|
* #category root
|
|
31
|
+
* Adds undo and redo of session changes to the root model, bound to Ctrl+Z
|
|
32
|
+
* and Ctrl+Y (Cmd on macOS).
|
|
31
33
|
*/
|
|
32
34
|
export function HistoryManagementMixin() {
|
|
33
35
|
return types
|
|
@@ -3,8 +3,9 @@ import type { ConfigurationSchemaDefinition } from '@jbrowse/core/configuration'
|
|
|
3
3
|
/**
|
|
4
4
|
* #config JBrowseConfiguration
|
|
5
5
|
* #category root
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Holds the app-wide settings in the `configuration` key of a config file,
|
|
7
|
+
* beside `assemblies` and `tracks`.
|
|
8
|
+
*
|
|
8
9
|
* ```json
|
|
9
10
|
* {
|
|
10
11
|
* assemblies,
|
|
@@ -5,8 +5,9 @@ import { DEFAULT_SHARE_URL } from './defaultShareUrl.js';
|
|
|
5
5
|
/**
|
|
6
6
|
* #config JBrowseConfiguration
|
|
7
7
|
* #category root
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Holds the app-wide settings in the `configuration` key of a config file,
|
|
9
|
+
* beside `assemblies` and `tracks`.
|
|
10
|
+
*
|
|
10
11
|
* ```json
|
|
11
12
|
* {
|
|
12
13
|
* assemblies,
|
|
@@ -6,9 +6,8 @@ export { DEFAULT_SHARE_URL } from './defaultShareUrl.ts';
|
|
|
6
6
|
* #config JBrowseRootConfig
|
|
7
7
|
* #category root
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* extension)
|
|
9
|
+
* Holds a whole JBrowse config file: the `config.json` of jbrowse-web, or a
|
|
10
|
+
* file with the `.jbrowse` extension in jbrowse-desktop.
|
|
12
11
|
*
|
|
13
12
|
* also includes any pluginManager.pluginConfigurationSchemas(), so plugins
|
|
14
13
|
* that have a configurationSchema field on their class are mixed into this
|
|
@@ -5,9 +5,8 @@ export { DEFAULT_SHARE_URL } from './defaultShareUrl.js';
|
|
|
5
5
|
* #config JBrowseRootConfig
|
|
6
6
|
* #category root
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* extension)
|
|
8
|
+
* Holds a whole JBrowse config file: the `config.json` of jbrowse-web, or a
|
|
9
|
+
* file with the `.jbrowse` extension in jbrowse-desktop.
|
|
11
10
|
*
|
|
12
11
|
* also includes any pluginManager.pluginConfigurationSchemas(), so plugins
|
|
13
12
|
* that have a configurationSchema field on their class are mixed into this
|
|
@@ -3,6 +3,14 @@ import type { BaseAssemblyConfigSchema } from '@jbrowse/core/assemblyManager';
|
|
|
3
3
|
import type { AnyConfiguration, AnyConfigurationModel, ConfigurationSchemaDefinition } from '@jbrowse/core/configuration';
|
|
4
4
|
import type { PluginDefinition } from '@jbrowse/core/pluginDefinitions';
|
|
5
5
|
import type RpcManager from '@jbrowse/core/rpc/RpcManager';
|
|
6
|
+
/**
|
|
7
|
+
* #stateModel AppCoreJBrowseModel
|
|
8
|
+
* #category root
|
|
9
|
+
* Holds the loaded config file, usually at `rootModel.jbrowse`, with actions
|
|
10
|
+
* that add and remove its assemblies and tracks. The model builds on the
|
|
11
|
+
* [JBrowseRootConfig](/docs/config/jbrowserootconfig) config model, which a
|
|
12
|
+
* state model can do because a config model is itself an MST tree.
|
|
13
|
+
*/
|
|
6
14
|
export declare function JBrowseModelF({ pluginManager, assemblyConfigSchema, extraConfigSlots, }: {
|
|
7
15
|
pluginManager: PluginManager;
|
|
8
16
|
assemblyConfigSchema: BaseAssemblyConfigSchema;
|
|
@@ -165,7 +173,7 @@ export declare function JBrowseModelF({ pluginManager, assemblyConfigSchema, ext
|
|
|
165
173
|
/**
|
|
166
174
|
* #action
|
|
167
175
|
*/
|
|
168
|
-
addAssemblyConf(conf:
|
|
176
|
+
addAssemblyConf(conf: AnyConfiguration): (import("@jbrowse/core/configuration").ConfigNodeProps<any> & import("@jbrowse/core/configuration").ConfigNodeActions & import("@jbrowse/core/configuration").ConfigNodeBrand<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>) | undefined;
|
|
169
177
|
/**
|
|
170
178
|
* #action
|
|
171
179
|
*/
|
|
@@ -6,13 +6,6 @@ import { expandLooseTrackConfig } from '@jbrowse/core/util/tracks';
|
|
|
6
6
|
import { cast, getParent, getSnapshot, isStateTreeNode, types, } from '@jbrowse/mobx-state-tree';
|
|
7
7
|
import { toJS } from 'mobx';
|
|
8
8
|
import { JBrowseConfigF } from '../JBrowseConfig/index.js';
|
|
9
|
-
/**
|
|
10
|
-
* #stateModel AppCoreJBrowseModel
|
|
11
|
-
* #category root
|
|
12
|
-
* built on the [JBrowseRootConfig](/docs/config/jbrowserootconfig) config model —
|
|
13
|
-
* config models are MST trees themselves, which is why this state model is
|
|
14
|
-
* allowed to build on one. Generally found on a property named rootModel.jbrowse
|
|
15
|
-
*/
|
|
16
9
|
// A config with exactly one assembly is what every loose track and search index
|
|
17
10
|
// is on, so `assemblyNames` may be left off; with several, each has to say.
|
|
18
11
|
function expandLooseTracks(snapshot, pluginManager) {
|
|
@@ -42,6 +35,14 @@ function expandLooseTracks(snapshot, pluginManager) {
|
|
|
42
35
|
: {}),
|
|
43
36
|
};
|
|
44
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* #stateModel AppCoreJBrowseModel
|
|
40
|
+
* #category root
|
|
41
|
+
* Holds the loaded config file, usually at `rootModel.jbrowse`, with actions
|
|
42
|
+
* that add and remove its assemblies and tracks. The model builds on the
|
|
43
|
+
* [JBrowseRootConfig](/docs/config/jbrowserootconfig) config model, which a
|
|
44
|
+
* state model can do because a config model is itself an MST tree.
|
|
45
|
+
*/
|
|
45
46
|
export function JBrowseModelF({ pluginManager, assemblyConfigSchema, extraConfigSlots, }) {
|
|
46
47
|
const model = JBrowseConfigF({
|
|
47
48
|
pluginManager,
|
package/esm/JbApi/jbApi.js
CHANGED
|
@@ -72,6 +72,9 @@ function displayState(track) {
|
|
|
72
72
|
return { display: display.type, error: String(e) };
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
+
function raisesPicker(views) {
|
|
76
|
+
return !!views?.some(view => view.searchPicker || raisesPicker(view.ownViews));
|
|
77
|
+
}
|
|
75
78
|
/**
|
|
76
79
|
* The drawer and any modal, for the same reason `offscreen` is reported: both
|
|
77
80
|
* are on top of the views in a screenshot that otherwise looks right.
|
|
@@ -94,7 +97,7 @@ function sessionChrome(session) {
|
|
|
94
97
|
},
|
|
95
98
|
}
|
|
96
99
|
: {};
|
|
97
|
-
const dialog = s.DialogComponent
|
|
100
|
+
const dialog = s.DialogComponent || raisesPicker(s.views)
|
|
98
101
|
? {
|
|
99
102
|
dialog: {
|
|
100
103
|
note: 'a modal dialog is open over the app, so a screenshot is of the dialog',
|
|
@@ -1024,7 +1027,7 @@ const JB_HELP = `jb drives this JBrowse app programmatically (window.jb in a bro
|
|
|
1024
1027
|
|
|
1025
1028
|
Orient first: jb.sessionSummary(). Introspect, never guess: jb.listTracks(search?, limit?) answers { total, tracks } with the trackIds; jb.describeSlots(jb.trackModel('someTrackId').activeDisplay.configuration) for the settings keys a display accepts — an unknown settings key is not an error, it lands in applyDisplaySettings' "unapplied" list as { key, reason }, so read the report; jb.inspect(node) — jb.view(), jb.trackModel('someTrackId'), session.views[0] — for its getters, actions and modelType.
|
|
1026
1029
|
|
|
1027
|
-
The model is mobx-state-tree: mutate only through actions (raw assignment throws), and write display settings with track.applyDisplaySettings(settings). A display's grammar settings are its plot, activeDisplay.plot, by slot name: facet ('strand' or { field, domain? }), color (a CSS color or { field: 'type', domain?, range? }), rows, unit (what a row stands for: 'read' | 'chain' on alignments, 'sample' | 'haplotype' on multi-sample variants), scales, filter (['jexl:feature.score > 10']), and on a mark display marks and transform. Edit structuredClone(activeDisplay.plot), check it with activeDisplay.plotProblems(draft), which throws what a config refuses, and write it with activeDisplay.applyPlot(draft): each setting replaced whole, null resetting one. An alignments track takes the same facet, its field a read dimension ('pairOrientation', 'mapq', ...) or a tag ('tags.HP'). LinearMarkDisplay plots a track's features as ggplot2 does, on a feature, alignments, variant or quantitative track, in seven settings: marks, a list drawn in order of { mark: 'bar' | 'point' | 'rule' | 'line' | 'span' | 'text' | 'link', encoding: { y: 'score', x?, x2?, row?, color?, shape?, text?, size? }, each a feature field or a jexl: expression, a constant written { value: 'red' }, transform?: steps such as { type: 'coverage' } or a bin then an aggregate, which fill the y they write, minBpPerPx?, maxBpPerPx? }, beside transform, facet, rows, rowColor, scales ({ y: { type, domainMin, domainMax, autoscaleGroup, title } }) and filter. await view.launchTrack(trackId, {}, { type: 'LinearMarkDisplay', marks: [...] }) draws a track with it, shown already or not (on a GWASTrack, type 'LinearManhattanDisplay'). activeDisplay.notices names a mark the config cannot draw, or one whose field no loaded feature holds. Build views declaratively with jb.loadSessionSpec({ views: [{ type: 'LinearGenomeView', assembly, loc, tracks: [...] }] }), which replaces the session; jb.addView(oneViewSpec) opens one more view beside what is open; jb.setSession(document) rewrites the session as a document — what jb.mst.getSnapshot(jb.session) answers, edited: a view keeps its id and is patched in place, loc on it navigates, a { trackId } entry in its tracks opens that track. Act on a view with await view.navToLocString('BRCA1' or 'chr1:1-1000'), which also SHOWS the track whose search index answered a gene name unless a 4th arg { showHitTrack: false } says not to; await view.launchTrack(trackId, {}, settings) shows a track with settings, view.hideTrack(trackId) hides it. Arrange open views into panels with session.layoutViews({ direction: 'horizontal', children: [{ views: [viewId] }, ...] }), a leaf naming view ids or session.views indexes; await jb.fitToWindow() shrinks what is open until the session fits the window; add data with jb.addTrack({ location }) (an absolute path or a URL), or show a track the catalog already holds with jb.addTrack({ trackId, settings? }); read data with await jb.getFeatures({ trackId, loc?, assembly?, viewId?, regions?, byteLimit? }), which renames refNames ("chr1" vs "1") so the file answers and reads on the worker the track's display uses. Anything lower level is jb.require('@jbrowse/core/util') and friends, the module registry plugins link against. After changing anything, await jb.waitReady(ms) and read its notifications and notReady lists before trusting the screen.
|
|
1030
|
+
The model is mobx-state-tree: mutate only through actions (raw assignment throws), and write display settings with track.applyDisplaySettings(settings). A display's grammar settings are its plot, activeDisplay.plot, by slot name: facet ('strand' or { field, domain? }), color (a CSS color or { field: 'type', domain?, range? }), rows, unit (what a row stands for: 'read' | 'chain' on alignments, 'sample' | 'haplotype' on multi-sample variants), sort (an alignments row order: 'split', or { type: 'strand', pos, refName }), scales, filter (['jexl:feature.score > 10']), and on a mark display marks and transform. Edit structuredClone(activeDisplay.plot), check it with activeDisplay.plotProblems(draft), which throws what a config refuses, and write it with activeDisplay.applyPlot(draft): each setting replaced whole, null resetting one. An alignments track takes the same facet, its field a read dimension ('pairOrientation', 'mapq', ...) or a tag ('tags.HP'). LinearMarkDisplay plots a track's features as ggplot2 does, on a feature, alignments, variant or quantitative track, in seven settings: marks, a list drawn in order of { mark: 'bar' | 'point' | 'rule' | 'line' | 'span' | 'text' | 'link', encoding: { y: 'score', x?, x2?, row?, color?, shape?, text?, size? }, each a feature field or a jexl: expression, a constant written { value: 'red' }, transform?: steps such as { type: 'coverage' } or a bin then an aggregate, which fill the y they write, minBpPerPx?, maxBpPerPx? }, beside transform, facet, rows, rowColor, scales ({ y: { type, domainMin, domainMax, autoscaleGroup, title } }) and filter. await view.launchTrack(trackId, {}, { type: 'LinearMarkDisplay', marks: [...] }) draws a track with it, shown already or not (on a GWASTrack, type 'LinearManhattanDisplay'). activeDisplay.notices names a mark the config cannot draw, or one whose field no loaded feature holds. Build views declaratively with jb.loadSessionSpec({ views: [{ type: 'LinearGenomeView', assembly, loc, tracks: [...] }] }), which replaces the session; jb.addView(oneViewSpec) opens one more view beside what is open; jb.setSession(document) rewrites the session as a document — what jb.mst.getSnapshot(jb.session) answers, edited: a view keeps its id and is patched in place, loc on it navigates, a { trackId } entry in its tracks opens that track. Act on a view with await view.navToLocString('BRCA1' or 'chr1:1-1000'), which also SHOWS the track whose search index answered a gene name unless a 4th arg { showHitTrack: false } says not to; await view.launchTrack(trackId, {}, settings) shows a track with settings, view.hideTrack(trackId) hides it. Arrange open views into panels with session.layoutViews({ direction: 'horizontal', children: [{ views: [viewId] }, ...] }), a leaf naming view ids or session.views indexes; await jb.fitToWindow() shrinks what is open until the session fits the window; add data with jb.addTrack({ location }) (an absolute path or a URL), or show a track the catalog already holds with jb.addTrack({ trackId, settings? }); read data with await jb.getFeatures({ trackId, loc?, assembly?, viewId?, regions?, byteLimit? }), which renames refNames ("chr1" vs "1") so the file answers and reads on the worker the track's display uses. Anything lower level is jb.require('@jbrowse/core/util') and friends, the module registry plugins link against. After changing anything, await jb.waitReady(ms) and read its notifications and notReady lists before trusting the screen.
|
|
1028
1031
|
|
|
1029
1032
|
Views nest and several can be open. jb.view(viewId?) is the open view, and jb.view(), jb.trackModel(trackId), jb.visibleRegions(), jb.addTrack and jb.getFeatures over a visible region throw naming the candidates rather than picking one when more than one view could answer — pass viewId (from jb.sessionSummary()) to say which. A synteny or breakpoint view's viewId also covers its rows: the named view answers when it can, and otherwise its rows do.
|
|
1030
1033
|
|
package/esm/RootMenu/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { MenuAction } from '../menus.ts';
|
|
|
2
2
|
import type { MenuItem } from '@jbrowse/core/ui/menuItems';
|
|
3
3
|
/**
|
|
4
4
|
* #stateModel RootAppMenuMixin
|
|
5
|
+
* Adds actions to the root model that let plugins add menus and menu items to
|
|
6
|
+
* the app bar.
|
|
5
7
|
*/
|
|
6
8
|
export declare function RootAppMenuMixin(): import("@jbrowse/mobx-state-tree").IModelType<{}, {
|
|
7
9
|
mutableMenuActions: MenuAction[];
|
package/esm/RootMenu/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { buildLgvInit, buildLgvInitFromParams, hubConnectionSpec, readHubUrlParam, readNavParam, readTracklistParam, shortHubLabel, splitHighlights, } from './lgvUrlInit.ts';
|
|
2
2
|
export { addSessionTracks, launchSpecView, launchableSpecView, loadSessionSpec, viewTypeProblem, } from './loadSessionSpec.ts';
|
|
3
|
-
export { parseSessionSpecUrl } from './parseSessionSpecUrl.ts';
|
|
3
|
+
export { parseSessionSnapshotUrl, parseSessionSpecUrl, } from './parseSessionSpecUrl.ts';
|
|
4
4
|
export type { LgvUrlInit } from './lgvUrlInit.ts';
|
|
5
|
-
export type { ParsedSessionSpec } from './parseSessionSpecUrl.ts';
|
|
5
|
+
export type { ParsedSessionSnapshotUrl, ParsedSessionSpec, } from './parseSessionSpecUrl.ts';
|
|
6
6
|
export type { LayoutNode, ViewSpec } from './types.ts';
|
package/esm/SessionSpec/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { buildLgvInit, buildLgvInitFromParams, hubConnectionSpec, readHubUrlParam, readNavParam, readTracklistParam, shortHubLabel, splitHighlights, } from './lgvUrlInit.js';
|
|
2
2
|
export { addSessionTracks, launchSpecView, launchableSpecView, loadSessionSpec, viewTypeProblem, } from './loadSessionSpec.js';
|
|
3
|
-
export { parseSessionSpecUrl } from './parseSessionSpecUrl.js';
|
|
3
|
+
export { parseSessionSnapshotUrl, parseSessionSpecUrl, } from './parseSessionSpecUrl.js';
|
|
@@ -4,4 +4,23 @@ export interface ParsedSessionSpec {
|
|
|
4
4
|
spec: Omit<SessionSpec, 'sessionName'>;
|
|
5
5
|
sessionName?: string;
|
|
6
6
|
}
|
|
7
|
+
export interface ParsedSessionSnapshotUrl {
|
|
8
|
+
configUrl: string;
|
|
9
|
+
/** the `session=` value as it is in the link, prefix included, undecoded */
|
|
10
|
+
session: string;
|
|
11
|
+
/** a `share-` link's key; the share service never sees it */
|
|
12
|
+
password?: string;
|
|
13
|
+
/** the JBrowse Web page the link points at, which a relative shareURL is relative to */
|
|
14
|
+
pageUrl: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The session snapshot a link hands over whole — carried in it (`encoded-…`,
|
|
18
|
+
* `json-…`) or stored by the share service under the id it names (`share-…`) —
|
|
19
|
+
* with the config it applies to. Undefined for any other link.
|
|
20
|
+
*
|
|
21
|
+
* A link with no `config=` means the instance's own `config.json`, as it does
|
|
22
|
+
* to the JBrowse Web page the link points at. A snapshot names assemblies and
|
|
23
|
+
* tracks by id and holds none of them, so there is always a config to fetch.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseSessionSnapshotUrl(input: string): ParsedSessionSnapshotUrl | undefined;
|
|
7
26
|
export declare function parseSessionSpecUrl(input: string): ParsedSessionSpec;
|
|
@@ -134,6 +134,35 @@ function readSessionTracks(params) {
|
|
|
134
134
|
}
|
|
135
135
|
return parsed;
|
|
136
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* The session snapshot a link hands over whole — carried in it (`encoded-…`,
|
|
139
|
+
* `json-…`) or stored by the share service under the id it names (`share-…`) —
|
|
140
|
+
* with the config it applies to. Undefined for any other link.
|
|
141
|
+
*
|
|
142
|
+
* A link with no `config=` means the instance's own `config.json`, as it does
|
|
143
|
+
* to the JBrowse Web page the link points at. A snapshot names assemblies and
|
|
144
|
+
* tracks by id and holds none of them, so there is always a config to fetch.
|
|
145
|
+
*/
|
|
146
|
+
export function parseSessionSnapshotUrl(input) {
|
|
147
|
+
let url;
|
|
148
|
+
try {
|
|
149
|
+
url = unwrapProtocolUrl(new URL(input.trim()));
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
const params = readAllQueryParams(url);
|
|
155
|
+
const session = params.get('session');
|
|
156
|
+
return session && /^(share|encoded|json)-/.test(session)
|
|
157
|
+
? {
|
|
158
|
+
configUrl: new URL(params.get('config') ?? 'config.json', url.href)
|
|
159
|
+
.href,
|
|
160
|
+
session,
|
|
161
|
+
password: params.get('password') ?? undefined,
|
|
162
|
+
pageUrl: url.href,
|
|
163
|
+
}
|
|
164
|
+
: undefined;
|
|
165
|
+
}
|
|
137
166
|
export function parseSessionSpecUrl(input) {
|
|
138
167
|
let url;
|
|
139
168
|
try {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Suspense, useCallback,
|
|
2
|
+
import { Suspense, useCallback, useMemo } from 'react';
|
|
3
3
|
import { makeStyles } from '@jbrowse/core/util/tss-react';
|
|
4
|
-
import { autorun } from 'mobx';
|
|
5
4
|
import { observer } from 'mobx-react';
|
|
6
5
|
import ViewStack from '../ui/App/ViewStack.js';
|
|
7
6
|
import { ViewLauncher } from '../ui/App/lazyParts.js';
|
|
@@ -27,13 +26,6 @@ const useStyles = makeStyles()(theme => ({
|
|
|
27
26
|
export const WorkspaceContainer = observer(function WorkspaceContainer({ session, }) {
|
|
28
27
|
const { classes } = useStyles();
|
|
29
28
|
const { drag, handlers } = useLayoutDrag(session);
|
|
30
|
-
// #region autorunInEffect
|
|
31
|
-
useEffect(() => autorun(() => {
|
|
32
|
-
// homes newly launched views; reads session.views here because an
|
|
33
|
-
// action's reads are untracked
|
|
34
|
-
session.homeUnassignedViews(session.views.map(v => v.id));
|
|
35
|
-
}), [session]);
|
|
36
|
-
// #endregion
|
|
37
29
|
// the layout does not own views, so every close gesture goes through here
|
|
38
30
|
// or leaks them
|
|
39
31
|
const closeViews = useCallback((viewIds) => {
|
|
@@ -65,7 +57,7 @@ export const WorkspaceContainer = observer(function WorkspaceContainer({ session
|
|
|
65
57
|
renderPanelActions: panel => (_jsx(WorkspacePanelActions, { panel: panel, session: session, onClose: () => {
|
|
66
58
|
closePanel(panel.id);
|
|
67
59
|
} })),
|
|
68
|
-
renderTabLabel: tab => (_jsx(WorkspaceTab, { tab: tab, views: viewsOf(session, tab.viewIds), session: session,
|
|
60
|
+
renderTabLabel: tab => (_jsx(WorkspaceTab, { tab: tab, views: viewsOf(session, tab.viewIds), session: session, onClose: () => {
|
|
69
61
|
closeTab(tab.id);
|
|
70
62
|
} })),
|
|
71
63
|
renderTabContent: tab => {
|
|
@@ -33,7 +33,7 @@ export const WorkspacePanelActions = observer(function WorkspacePanelActions({ p
|
|
|
33
33
|
const canClose = session.panels.length > 1;
|
|
34
34
|
const maximized = session.maximizedPanelId === panel.id;
|
|
35
35
|
const tile = (mode) => {
|
|
36
|
-
session.tileViews(mode
|
|
36
|
+
session.tileViews(mode);
|
|
37
37
|
};
|
|
38
38
|
return (_jsxs("div", { className: classes.actions, children: [_jsx(CascadingMenuButton, { menuItems: [
|
|
39
39
|
{
|
|
@@ -2,11 +2,10 @@ import type { WorkspaceSessionType } from '../ui/App/types.ts';
|
|
|
2
2
|
import type { WorkspaceLayout } from './model.ts';
|
|
3
3
|
import type { TabNode } from './tree.ts';
|
|
4
4
|
import type { AbstractViewModel } from '@jbrowse/core/util';
|
|
5
|
-
export declare const WorkspaceTab: ({ tab, views, session,
|
|
5
|
+
export declare const WorkspaceTab: ({ tab, views, session, onClose, }: {
|
|
6
6
|
tab: TabNode;
|
|
7
7
|
views: AbstractViewModel[];
|
|
8
|
-
session: WorkspaceSessionType;
|
|
9
|
-
layout: WorkspaceLayout;
|
|
8
|
+
session: WorkspaceSessionType & WorkspaceLayout;
|
|
10
9
|
/** closes the tab and the views it holds */
|
|
11
10
|
onClose: () => void;
|
|
12
11
|
}) => import("react").JSX.Element;
|
|
@@ -31,7 +31,7 @@ const useStyles = makeStyles()(theme => ({
|
|
|
31
31
|
flex: 1,
|
|
32
32
|
},
|
|
33
33
|
}));
|
|
34
|
-
export const WorkspaceTab = observer(function WorkspaceTab({ tab, views, session,
|
|
34
|
+
export const WorkspaceTab = observer(function WorkspaceTab({ tab, views, session, onClose, }) {
|
|
35
35
|
const { classes } = useStyles();
|
|
36
36
|
const [editing, setEditing] = useState(false);
|
|
37
37
|
const [draft, setDraft] = useState('');
|
|
@@ -44,7 +44,7 @@ export const WorkspaceTab = observer(function WorkspaceTab({ tab, views, session
|
|
|
44
44
|
const save = () => {
|
|
45
45
|
const name = draft.trim();
|
|
46
46
|
const automatic = tabDisplayName({ ...tab, title: undefined }, views, session);
|
|
47
|
-
|
|
47
|
+
session.renameTab(tab.id, name && name !== automatic ? name : undefined);
|
|
48
48
|
setEditing(false);
|
|
49
49
|
};
|
|
50
50
|
return (_jsx("div", { className: classes.tab, children: editing ? (_jsx(InputBase, { autoFocus: true, className: classes.editInput, value: draft, onChange: e => {
|
|
@@ -97,10 +97,6 @@ export declare function WorkspaceLayoutMixin(): import("@jbrowse/mobx-state-tree
|
|
|
97
97
|
findTab(tabId: string): TabHome | undefined;
|
|
98
98
|
tabContainingView(viewId: string): TabHome | undefined;
|
|
99
99
|
panelContainingView(viewId: string): PanelNode | undefined;
|
|
100
|
-
/** The views a tab renders: its members, in `session.views` order. */
|
|
101
|
-
viewIdsForTab(tabId: string, order: string[]): string[];
|
|
102
|
-
/** The tab a panel is showing, or its first. */
|
|
103
|
-
activeTabOf(panelId: string): TabNode | undefined;
|
|
104
100
|
/**
|
|
105
101
|
* The maximized cell alone, or the whole tree. The cell is resized to 1
|
|
106
102
|
* because CSS hands out free space by grow factor only up to a total of
|
|
@@ -144,35 +140,32 @@ export declare function WorkspaceLayoutMixin(): import("@jbrowse/mobx-state-tree
|
|
|
144
140
|
applyLayoutSpec(spec: LayoutSpecNode): string[];
|
|
145
141
|
/**
|
|
146
142
|
* ViewMenu's "move to new tab": the view leaves its tab for a new one.
|
|
147
|
-
* `allViewIds` is EVERY view in the session, defaulting to the host's
|
|
148
|
-
* own list, since homing drops any view the list omits.
|
|
149
143
|
*/
|
|
150
|
-
moveViewToNewTab(viewId: string
|
|
144
|
+
moveViewToNewTab(viewId: string): string | undefined;
|
|
151
145
|
/**
|
|
152
146
|
* ViewMenu's "move to split": the view leaves for a new cell to the
|
|
153
147
|
* right (`row`) or below (`column`) of its own.
|
|
154
148
|
*/
|
|
155
|
-
moveViewToSplit(viewId: string, direction: 'row' | 'column'
|
|
149
|
+
moveViewToSplit(viewId: string, direction: 'row' | 'column'): string | undefined;
|
|
156
150
|
/**
|
|
157
151
|
* ViewMenu's "move to tab": the view joins an existing tab, which
|
|
158
152
|
* becomes the one shown.
|
|
159
153
|
*/
|
|
160
|
-
moveViewToTab(viewId: string, tabId: string
|
|
154
|
+
moveViewToTab(viewId: string, tabId: string): void;
|
|
161
155
|
homeUnassignedViews(viewIds: string[]): void;
|
|
162
156
|
} & {
|
|
163
157
|
/**
|
|
164
158
|
* Move one view to a new tab or a split beside its cell, keeping the
|
|
165
159
|
* rest of the arrangement. PUBLIC API: protein3d and msaview call it
|
|
166
|
-
* with the move alone
|
|
167
|
-
*
|
|
160
|
+
* with the move alone. The second argument is an old plugin signature;
|
|
161
|
+
* the session's own views are read instead.
|
|
168
162
|
*/
|
|
169
|
-
setPendingMove(move: PendingMove | undefined,
|
|
163
|
+
setPendingMove(move: PendingMove | undefined, _allViewIds?: string[]): void;
|
|
170
164
|
/**
|
|
171
165
|
* Re-arrange the whole workspace, one view per cell, in one of four
|
|
172
|
-
* shapes
|
|
173
|
-
* nothing for `orderViews` to apply.
|
|
166
|
+
* shapes, in `session.views` order.
|
|
174
167
|
*/
|
|
175
|
-
tileViews(mode: TileMode
|
|
168
|
+
tileViews(mode: TileMode): void;
|
|
176
169
|
/**
|
|
177
170
|
* #action
|
|
178
171
|
* Arrange the session's views into panels: `applyLayoutSpec`, then
|
|
@@ -183,6 +176,8 @@ export declare function WorkspaceLayoutMixin(): import("@jbrowse/mobx-state-tree
|
|
|
183
176
|
* re-layout both call it.
|
|
184
177
|
*/
|
|
185
178
|
layoutViews(spec: LayoutSpecNode): string[];
|
|
179
|
+
} & {
|
|
180
|
+
afterAttach(): void;
|
|
186
181
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
|
|
187
182
|
export type WorkspaceLayoutMixinType = ReturnType<typeof WorkspaceLayoutMixin>;
|
|
188
183
|
export interface WorkspaceLayout extends Instance<WorkspaceLayoutMixinType> {
|