@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,46 @@
|
|
|
1
|
+
import { types } from 'mobx-state-tree';
|
|
2
|
+
import { BaseSessionModel, isBaseSession } from './BaseSession';
|
|
3
|
+
import { ReferenceManagementSessionMixin } from './ReferenceManagement';
|
|
4
|
+
/**
|
|
5
|
+
* #stateModel TracksManagerSessionMixin
|
|
6
|
+
* composed of
|
|
7
|
+
* - BaseSessionModel
|
|
8
|
+
* - ReferenceManagementSessionMixin
|
|
9
|
+
*/
|
|
10
|
+
export function TracksManagerSessionMixin(pluginManager) {
|
|
11
|
+
return types
|
|
12
|
+
.compose('TracksManagerSessionMixin', BaseSessionModel(pluginManager), ReferenceManagementSessionMixin(pluginManager))
|
|
13
|
+
.views(self => ({
|
|
14
|
+
/**
|
|
15
|
+
* #getter
|
|
16
|
+
*/
|
|
17
|
+
get tracks() {
|
|
18
|
+
return self.jbrowse.tracks;
|
|
19
|
+
},
|
|
20
|
+
}))
|
|
21
|
+
.actions(self => ({
|
|
22
|
+
/**
|
|
23
|
+
* #action
|
|
24
|
+
*/
|
|
25
|
+
addTrackConf(trackConf) {
|
|
26
|
+
return self.jbrowse.addTrackConf(trackConf);
|
|
27
|
+
},
|
|
28
|
+
/**
|
|
29
|
+
* #action
|
|
30
|
+
*/
|
|
31
|
+
deleteTrackConf(trackConf) {
|
|
32
|
+
const callbacksToDereferenceTrack = [];
|
|
33
|
+
const dereferenceTypeCount = {};
|
|
34
|
+
const referring = self.getReferring(trackConf);
|
|
35
|
+
self.removeReferring(referring, trackConf, callbacksToDereferenceTrack, dereferenceTypeCount);
|
|
36
|
+
callbacksToDereferenceTrack.forEach(cb => cb());
|
|
37
|
+
if (self.adminMode) {
|
|
38
|
+
return self.jbrowse.deleteTrackConf(trackConf);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
/** Type guard for SessionWithTracks */
|
|
44
|
+
export function isSessionWithTracks(thing) {
|
|
45
|
+
return isBaseSession(thing) && 'tracks' in thing;
|
|
46
|
+
}
|
|
@@ -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';
|
|
@@ -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/esm/index.d.ts
ADDED
package/esm/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Dialog from '@jbrowse/core/ui/Dialog';
|
|
3
|
+
import { getSession, getEnv } from '@jbrowse/core/util';
|
|
4
|
+
import { getTrackName } from '@jbrowse/core/util/tracks';
|
|
5
|
+
import AboutContents from './AboutDialogContents';
|
|
6
|
+
export function AboutDialog({ config, handleClose, }) {
|
|
7
|
+
const session = getSession(config);
|
|
8
|
+
const trackName = getTrackName(config, session);
|
|
9
|
+
const { pluginManager } = getEnv(session);
|
|
10
|
+
const AboutComponent = pluginManager.evaluateExtensionPoint('Core-replaceAbout', AboutContents, { session, config });
|
|
11
|
+
return (React.createElement(Dialog, { open: true, onClose: handleClose, title: trackName, maxWidth: "xl" },
|
|
12
|
+
React.createElement(AboutComponent, { config: config })));
|
|
13
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
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 { getConf, readConfObject, } from '@jbrowse/core/configuration';
|
|
6
|
+
import { getSession, getEnv } from '@jbrowse/core/util';
|
|
7
|
+
import { BaseCard, Attributes, } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail';
|
|
8
|
+
import FileInfoPanel from './FileInfoPanel';
|
|
9
|
+
const useStyles = makeStyles()({
|
|
10
|
+
content: {
|
|
11
|
+
minWidth: 800,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
export default function AboutContents({ config, }) {
|
|
15
|
+
const [copied, setCopied] = useState(false);
|
|
16
|
+
const conf = readConfObject(config);
|
|
17
|
+
const session = getSession(config);
|
|
18
|
+
const { classes } = useStyles();
|
|
19
|
+
const hideUris = getConf(session, ['formatAbout', 'hideUris']) ||
|
|
20
|
+
readConfObject(config, ['formatAbout', 'hideUris']);
|
|
21
|
+
const { pluginManager } = getEnv(session);
|
|
22
|
+
const confPostExt = pluginManager.evaluateExtensionPoint('Core-customizeAbout', {
|
|
23
|
+
config: {
|
|
24
|
+
...conf,
|
|
25
|
+
...getConf(session, ['formatAbout', 'config'], { config: conf }),
|
|
26
|
+
...readConfObject(config, ['formatAbout', 'config'], { config: conf }),
|
|
27
|
+
},
|
|
28
|
+
}, { session, config });
|
|
29
|
+
const ExtraPanel = pluginManager.evaluateExtensionPoint('Core-extraAboutPanel', null, { session, config });
|
|
30
|
+
return (React.createElement("div", { className: classes.content },
|
|
31
|
+
React.createElement(BaseCard, { title: "Configuration" },
|
|
32
|
+
!hideUris ? (React.createElement(Button, { variant: "contained", style: { float: 'right' }, onClick: () => {
|
|
33
|
+
copy(JSON.stringify(conf, null, 2));
|
|
34
|
+
setCopied(true);
|
|
35
|
+
setTimeout(() => setCopied(false), 1000);
|
|
36
|
+
} }, copied ? 'Copied to clipboard!' : 'Copy config')) : null,
|
|
37
|
+
React.createElement(Attributes, { attributes: confPostExt, omit: ['displays', 'baseUri', 'refNames', 'formatAbout'], hideUris: hideUris })),
|
|
38
|
+
ExtraPanel ? (React.createElement(BaseCard, { title: ExtraPanel.name },
|
|
39
|
+
React.createElement(ExtraPanel.Component, { config: config }))) : null,
|
|
40
|
+
React.createElement(FileInfoPanel, { config: config })));
|
|
41
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { Typography } from '@mui/material';
|
|
3
|
+
import { readConfObject, } from '@jbrowse/core/configuration';
|
|
4
|
+
import LoadingEllipses from '@jbrowse/core/ui/LoadingEllipses';
|
|
5
|
+
import { getSession } from '@jbrowse/core/util';
|
|
6
|
+
import { BaseCard, Attributes, } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail';
|
|
7
|
+
export default function FileInfoPanel({ config, }) {
|
|
8
|
+
const [error, setError] = useState();
|
|
9
|
+
const [info, setInfo] = useState();
|
|
10
|
+
const session = getSession(config);
|
|
11
|
+
const { rpcManager } = session;
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const aborter = new AbortController();
|
|
14
|
+
const { signal } = aborter;
|
|
15
|
+
let cancelled = false;
|
|
16
|
+
(async () => {
|
|
17
|
+
try {
|
|
18
|
+
const adapterConfig = readConfObject(config, 'adapter');
|
|
19
|
+
const result = await rpcManager.call(config.trackId, 'CoreGetInfo', {
|
|
20
|
+
adapterConfig,
|
|
21
|
+
signal,
|
|
22
|
+
});
|
|
23
|
+
if (!cancelled) {
|
|
24
|
+
setInfo(result);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
if (!cancelled) {
|
|
29
|
+
console.error(e);
|
|
30
|
+
setError(e);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
})();
|
|
34
|
+
return () => {
|
|
35
|
+
aborter.abort();
|
|
36
|
+
cancelled = true;
|
|
37
|
+
};
|
|
38
|
+
}, [config, rpcManager]);
|
|
39
|
+
const details = typeof info === 'string'
|
|
40
|
+
? {
|
|
41
|
+
header: `<pre>${info
|
|
42
|
+
.replaceAll('<', '<')
|
|
43
|
+
.replaceAll('>', '>')}</pre>`,
|
|
44
|
+
}
|
|
45
|
+
: info || {};
|
|
46
|
+
return info !== null ? (React.createElement(BaseCard, { title: "File info" }, error ? (React.createElement(Typography, { color: "error" }, `${error}`)) : info === undefined ? (React.createElement(LoadingEllipses, { message: "Loading file data" })) : (React.createElement(Attributes, { attributes: details })))) : null;
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './AboutDialog';
|
package/esm/ui/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './AboutDialog';
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jbrowse/product-core",
|
|
3
|
+
"version": "2.6.1",
|
|
4
|
+
"sideEffects": false,
|
|
5
|
+
"description": "JBrowse 2 code shared between products but not used by plugins",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"jbrowse",
|
|
8
|
+
"jbrowse2",
|
|
9
|
+
"bionode",
|
|
10
|
+
"biojs",
|
|
11
|
+
"genomics"
|
|
12
|
+
],
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"homepage": "https://jbrowse.org",
|
|
15
|
+
"bugs": "https://github.com/GMOD/jbrowse-components/issues",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/GMOD/jbrowse-components.git",
|
|
19
|
+
"directory": "packages/product-core"
|
|
20
|
+
},
|
|
21
|
+
"author": "JBrowse Team",
|
|
22
|
+
"distMain": "dist/index.js",
|
|
23
|
+
"distModule": "esm/index.js",
|
|
24
|
+
"srcMain": "src/index.ts",
|
|
25
|
+
"srcModule": "src/index.ts",
|
|
26
|
+
"main": "dist/index.js",
|
|
27
|
+
"module": "esm/index.js",
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"esm",
|
|
31
|
+
"src"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build:esm": "tsc --build tsconfig.build.esm.json",
|
|
35
|
+
"build:es5": "tsc --build tsconfig.build.es5.json",
|
|
36
|
+
"build": "npm run build:esm && npm run build:es5",
|
|
37
|
+
"test": "cd ../..; jest packages/product-core",
|
|
38
|
+
"clean": "rimraf dist esm *.tsbuildinfo",
|
|
39
|
+
"prebuild": "yarn clean",
|
|
40
|
+
"prepack": "yarn build && yarn useDist",
|
|
41
|
+
"postpack": "yarn useSrc",
|
|
42
|
+
"useDist": "node ../../scripts/useDist.js",
|
|
43
|
+
"useSrc": "node ../../scripts/useSrc.js"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@babel/runtime": "^7.16.3",
|
|
47
|
+
"@mui/icons-material": "^5.0.0",
|
|
48
|
+
"@mui/material": "^5.10.17",
|
|
49
|
+
"copy-to-clipboard": "^3.3.1",
|
|
50
|
+
"react-error-boundary": "^4.0.3",
|
|
51
|
+
"shortid": "^2.2.15"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"mobx": "^6.0.0",
|
|
55
|
+
"mobx-react": "^7.0.0",
|
|
56
|
+
"mobx-state-tree": "^5.0.0",
|
|
57
|
+
"react": "^17.0.0",
|
|
58
|
+
"react-dom": "^17.0.0",
|
|
59
|
+
"rxjs": "^7.0.0",
|
|
60
|
+
"tss-react": "^4.0.0"
|
|
61
|
+
},
|
|
62
|
+
"publishConfig": {
|
|
63
|
+
"access": "public"
|
|
64
|
+
},
|
|
65
|
+
"gitHead": "1cbe7ba097fb2d2763c776e5e429e4670cdd583c"
|
|
66
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
|
+
import assemblyManagerFactory, {
|
|
3
|
+
BaseAssemblyConfigSchema,
|
|
4
|
+
} from '@jbrowse/core/assemblyManager'
|
|
5
|
+
import RpcManager from '@jbrowse/core/rpc/RpcManager'
|
|
6
|
+
import {
|
|
7
|
+
IAnyType,
|
|
8
|
+
Instance,
|
|
9
|
+
SnapshotIn,
|
|
10
|
+
cast,
|
|
11
|
+
getSnapshot,
|
|
12
|
+
isStateTreeNode,
|
|
13
|
+
types,
|
|
14
|
+
} from 'mobx-state-tree'
|
|
15
|
+
import TextSearchManager from '@jbrowse/core/TextSearch/TextSearchManager'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* #stateModel BaseRootModel
|
|
19
|
+
* #category root
|
|
20
|
+
* factory function for the Base-level root model shared by all products
|
|
21
|
+
*/
|
|
22
|
+
export function BaseRootModelFactory({
|
|
23
|
+
pluginManager,
|
|
24
|
+
jbrowseModelType,
|
|
25
|
+
sessionModelType,
|
|
26
|
+
assemblyConfigSchema,
|
|
27
|
+
}: {
|
|
28
|
+
pluginManager: PluginManager
|
|
29
|
+
jbrowseModelType: IAnyType
|
|
30
|
+
sessionModelType: IAnyType
|
|
31
|
+
assemblyConfigSchema: BaseAssemblyConfigSchema
|
|
32
|
+
}) {
|
|
33
|
+
return types
|
|
34
|
+
.model('BaseRootModel', {
|
|
35
|
+
/**
|
|
36
|
+
* #property
|
|
37
|
+
* `jbrowse` is a mapping of the config.json into the in-memory state
|
|
38
|
+
* tree
|
|
39
|
+
*/
|
|
40
|
+
jbrowse: jbrowseModelType,
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* #property
|
|
44
|
+
* `session` encompasses the currently active state of the app, including
|
|
45
|
+
* views open, tracks open in those views, etc.
|
|
46
|
+
*/
|
|
47
|
+
session: types.maybe(sessionModelType),
|
|
48
|
+
/**
|
|
49
|
+
* #property
|
|
50
|
+
*/
|
|
51
|
+
sessionPath: types.optional(types.string, ''),
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* #property
|
|
55
|
+
*/
|
|
56
|
+
assemblyManager: types.optional(
|
|
57
|
+
assemblyManagerFactory(assemblyConfigSchema, pluginManager),
|
|
58
|
+
{},
|
|
59
|
+
),
|
|
60
|
+
})
|
|
61
|
+
.volatile(self => ({
|
|
62
|
+
rpcManager: new RpcManager(
|
|
63
|
+
pluginManager,
|
|
64
|
+
self.jbrowse.configuration.rpc,
|
|
65
|
+
{
|
|
66
|
+
MainThreadRpcDriver: {},
|
|
67
|
+
},
|
|
68
|
+
),
|
|
69
|
+
|
|
70
|
+
adminMode: false,
|
|
71
|
+
isAssemblyEditing: false,
|
|
72
|
+
error: undefined as unknown,
|
|
73
|
+
textSearchManager: new TextSearchManager(pluginManager),
|
|
74
|
+
pluginManager,
|
|
75
|
+
}))
|
|
76
|
+
.actions(self => ({
|
|
77
|
+
/**
|
|
78
|
+
* #action
|
|
79
|
+
*/
|
|
80
|
+
setError(error: unknown) {
|
|
81
|
+
self.error = error
|
|
82
|
+
},
|
|
83
|
+
/**
|
|
84
|
+
* #action
|
|
85
|
+
*/
|
|
86
|
+
setSession(sessionSnapshot?: SnapshotIn<IAnyType>) {
|
|
87
|
+
self.session = cast(sessionSnapshot)
|
|
88
|
+
},
|
|
89
|
+
/**
|
|
90
|
+
* #action
|
|
91
|
+
*/
|
|
92
|
+
setDefaultSession() {
|
|
93
|
+
this.setSession(self.jbrowse.defaultSession)
|
|
94
|
+
},
|
|
95
|
+
/**
|
|
96
|
+
* #action
|
|
97
|
+
*/
|
|
98
|
+
setSessionPath(path: string) {
|
|
99
|
+
self.sessionPath = path
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
* #action
|
|
103
|
+
*/
|
|
104
|
+
renameCurrentSession(newName: string) {
|
|
105
|
+
if (self.session) {
|
|
106
|
+
const snapshot = JSON.parse(JSON.stringify(getSnapshot(self.session)))
|
|
107
|
+
snapshot.name = newName
|
|
108
|
+
this.setSession(snapshot)
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
/**
|
|
112
|
+
* #action
|
|
113
|
+
*/
|
|
114
|
+
setAssemblyEditing(flag: boolean) {
|
|
115
|
+
self.isAssemblyEditing = flag
|
|
116
|
+
},
|
|
117
|
+
}))
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export type BaseRootModelType = ReturnType<typeof BaseRootModelFactory>
|
|
121
|
+
export type BaseRootModel = Instance<BaseRootModelType>
|
|
122
|
+
|
|
123
|
+
/** Type guard for checking if something is a JB root model */
|
|
124
|
+
export function isRootModel(thing: unknown): thing is BaseRootModelType {
|
|
125
|
+
return (
|
|
126
|
+
isStateTreeNode(thing) &&
|
|
127
|
+
'session' in thing &&
|
|
128
|
+
'jbrowse' in thing &&
|
|
129
|
+
'assemblyManager' in thing
|
|
130
|
+
)
|
|
131
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
|
+
import { AnyConfigurationModel } from '@jbrowse/core/configuration'
|
|
3
|
+
import { UriLocation } from '@jbrowse/core/util'
|
|
4
|
+
import { autorun } from 'mobx'
|
|
5
|
+
import { Instance, addDisposer, types } from 'mobx-state-tree'
|
|
6
|
+
import { BaseRootModel } from './BaseRootModel'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* #stateModel InternetAccountsMixin
|
|
10
|
+
* #category root
|
|
11
|
+
*/
|
|
12
|
+
export function InternetAccountsRootModelMixin(pluginManager: PluginManager) {
|
|
13
|
+
return types
|
|
14
|
+
.model({
|
|
15
|
+
/**
|
|
16
|
+
* #property
|
|
17
|
+
*/
|
|
18
|
+
internetAccounts: types.array(
|
|
19
|
+
pluginManager.pluggableMstType('internet account', 'stateModel'),
|
|
20
|
+
),
|
|
21
|
+
})
|
|
22
|
+
.actions(self => ({
|
|
23
|
+
/**
|
|
24
|
+
* #action
|
|
25
|
+
*/
|
|
26
|
+
initializeInternetAccount(
|
|
27
|
+
internetAccountConfig: AnyConfigurationModel,
|
|
28
|
+
initialSnapshot = {},
|
|
29
|
+
) {
|
|
30
|
+
const internetAccountType = pluginManager.getInternetAccountType(
|
|
31
|
+
internetAccountConfig.type,
|
|
32
|
+
)
|
|
33
|
+
if (!internetAccountType) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`unknown internet account type ${internetAccountConfig.type}`,
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const length = self.internetAccounts.push({
|
|
40
|
+
...initialSnapshot,
|
|
41
|
+
type: internetAccountConfig.type,
|
|
42
|
+
configuration: internetAccountConfig,
|
|
43
|
+
})
|
|
44
|
+
return self.internetAccounts[length - 1]
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* #action
|
|
49
|
+
*/
|
|
50
|
+
createEphemeralInternetAccount(
|
|
51
|
+
internetAccountId: string,
|
|
52
|
+
initialSnapshot = {},
|
|
53
|
+
url: string,
|
|
54
|
+
) {
|
|
55
|
+
let hostUri
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
hostUri = new URL(url).origin
|
|
59
|
+
} catch (e) {
|
|
60
|
+
// ignore
|
|
61
|
+
}
|
|
62
|
+
// id of a custom new internaccount is `${type}-${name}`
|
|
63
|
+
const internetAccountSplit = internetAccountId.split('-')
|
|
64
|
+
const configuration = {
|
|
65
|
+
type: internetAccountSplit[0],
|
|
66
|
+
internetAccountId: internetAccountId,
|
|
67
|
+
name: internetAccountSplit.slice(1).join('-'),
|
|
68
|
+
description: '',
|
|
69
|
+
domains: hostUri ? [hostUri] : [],
|
|
70
|
+
}
|
|
71
|
+
const type = pluginManager.getInternetAccountType(configuration.type)
|
|
72
|
+
const internetAccount = type.stateModel.create({
|
|
73
|
+
...initialSnapshot,
|
|
74
|
+
type: configuration.type,
|
|
75
|
+
configuration,
|
|
76
|
+
})
|
|
77
|
+
self.internetAccounts.push(internetAccount)
|
|
78
|
+
return internetAccount
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* #action
|
|
82
|
+
*/
|
|
83
|
+
findAppropriateInternetAccount(location: UriLocation) {
|
|
84
|
+
// find the existing account selected from menu
|
|
85
|
+
const selectedId = location.internetAccountId
|
|
86
|
+
if (selectedId) {
|
|
87
|
+
const selectedAccount = self.internetAccounts.find(account => {
|
|
88
|
+
return account.internetAccountId === selectedId
|
|
89
|
+
})
|
|
90
|
+
if (selectedAccount) {
|
|
91
|
+
return selectedAccount
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// if no existing account or not found, try to find working account
|
|
96
|
+
for (const account of self.internetAccounts) {
|
|
97
|
+
const handleResult = account.handlesLocation(location)
|
|
98
|
+
if (handleResult) {
|
|
99
|
+
return account
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// if still no existing account, create ephemeral config to use
|
|
104
|
+
return selectedId
|
|
105
|
+
? this.createEphemeralInternetAccount(selectedId, {}, location.uri)
|
|
106
|
+
: null
|
|
107
|
+
},
|
|
108
|
+
}))
|
|
109
|
+
.actions(self => ({
|
|
110
|
+
afterCreate() {
|
|
111
|
+
addDisposer(
|
|
112
|
+
self,
|
|
113
|
+
autorun(() => {
|
|
114
|
+
const { jbrowse } = self as typeof self & BaseRootModel
|
|
115
|
+
jbrowse.internetAccounts.forEach(self.initializeInternetAccount)
|
|
116
|
+
}),
|
|
117
|
+
)
|
|
118
|
+
},
|
|
119
|
+
}))
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export type RootModelWithInternetAccountsType = ReturnType<
|
|
123
|
+
typeof InternetAccountsRootModelMixin
|
|
124
|
+
>
|
|
125
|
+
export type RootModelWithInternetAccounts =
|
|
126
|
+
Instance<RootModelWithInternetAccountsType>
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import shortid from 'shortid'
|
|
2
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
3
|
+
import {
|
|
4
|
+
IAnyStateTreeNode,
|
|
5
|
+
Instance,
|
|
6
|
+
getParent,
|
|
7
|
+
isStateTreeNode,
|
|
8
|
+
types,
|
|
9
|
+
} from 'mobx-state-tree'
|
|
10
|
+
import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration'
|
|
11
|
+
import { BaseAssemblyConfigSchema } from '@jbrowse/core/assemblyManager'
|
|
12
|
+
|
|
13
|
+
// locals
|
|
14
|
+
import type { BaseRootModelType } from '../RootModel/BaseRootModel'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* #stateModel BaseSessionModel
|
|
18
|
+
* base session shared by **all** JBrowse products. Be careful what you include
|
|
19
|
+
* here, everything will use it.
|
|
20
|
+
*/
|
|
21
|
+
export function BaseSessionModel<
|
|
22
|
+
ROOT_MODEL_TYPE extends BaseRootModelType,
|
|
23
|
+
JB_CONFIG_SCHEMA extends AnyConfigurationSchemaType,
|
|
24
|
+
>(pluginManager: PluginManager) {
|
|
25
|
+
return types
|
|
26
|
+
.model({
|
|
27
|
+
/**
|
|
28
|
+
* #property
|
|
29
|
+
*/
|
|
30
|
+
id: types.optional(types.identifier, shortid()),
|
|
31
|
+
/**
|
|
32
|
+
* #property
|
|
33
|
+
*/
|
|
34
|
+
name: types.string,
|
|
35
|
+
/**
|
|
36
|
+
* #property
|
|
37
|
+
*/
|
|
38
|
+
margin: 0,
|
|
39
|
+
})
|
|
40
|
+
.volatile(() => ({
|
|
41
|
+
/**
|
|
42
|
+
* #volatile
|
|
43
|
+
* this is the globally "selected" object. can be anything. code that
|
|
44
|
+
* wants to deal with this should examine it to see what kind of thing it
|
|
45
|
+
* is.
|
|
46
|
+
*/
|
|
47
|
+
selection: undefined as unknown,
|
|
48
|
+
}))
|
|
49
|
+
.views(self => ({
|
|
50
|
+
get root() {
|
|
51
|
+
return getParent<ROOT_MODEL_TYPE>(self)
|
|
52
|
+
},
|
|
53
|
+
}))
|
|
54
|
+
.views(self => ({
|
|
55
|
+
/**
|
|
56
|
+
* #getter
|
|
57
|
+
*/
|
|
58
|
+
get jbrowse() {
|
|
59
|
+
return self.root.jbrowse
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* #getter
|
|
63
|
+
*/
|
|
64
|
+
get rpcManager() {
|
|
65
|
+
return self.root.rpcManager
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* #getter
|
|
69
|
+
*/
|
|
70
|
+
get configuration(): Instance<JB_CONFIG_SCHEMA> {
|
|
71
|
+
return this.jbrowse.configuration
|
|
72
|
+
},
|
|
73
|
+
/**
|
|
74
|
+
* #getter
|
|
75
|
+
*/
|
|
76
|
+
get adminMode() {
|
|
77
|
+
return self.root.adminMode
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* #getter
|
|
82
|
+
*/
|
|
83
|
+
get textSearchManager() {
|
|
84
|
+
return self.root.textSearchManager
|
|
85
|
+
},
|
|
86
|
+
}))
|
|
87
|
+
.views(self => ({
|
|
88
|
+
/**
|
|
89
|
+
* #getter
|
|
90
|
+
*/
|
|
91
|
+
get assemblies(): Instance<BaseAssemblyConfigSchema>[] {
|
|
92
|
+
return self.jbrowse.assemblies
|
|
93
|
+
},
|
|
94
|
+
}))
|
|
95
|
+
.actions(self => ({
|
|
96
|
+
/**
|
|
97
|
+
* #action
|
|
98
|
+
* set the global selection, i.e. the globally-selected object. can be a
|
|
99
|
+
* feature, a view, just about anything
|
|
100
|
+
*/
|
|
101
|
+
setSelection(thing: unknown) {
|
|
102
|
+
self.selection = thing
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* #action
|
|
107
|
+
* clears the global selection
|
|
108
|
+
*/
|
|
109
|
+
clearSelection() {
|
|
110
|
+
self.selection = undefined
|
|
111
|
+
},
|
|
112
|
+
}))
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Session mixin MST type for the most basic session */
|
|
116
|
+
export type BaseSessionType = ReturnType<typeof BaseSessionModel>
|
|
117
|
+
|
|
118
|
+
/** Instance of the most basic possible session */
|
|
119
|
+
export type BaseSession = Instance<BaseSessionType>
|
|
120
|
+
|
|
121
|
+
/** Type guard for BaseSession */
|
|
122
|
+
export function isBaseSession(thing: IAnyStateTreeNode): thing is BaseSession {
|
|
123
|
+
return 'id' in thing && 'name' in thing && 'root' in thing
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Type guard for whether a thing is JBrowse session */
|
|
127
|
+
export function isSession(thing: unknown): thing is BaseSession {
|
|
128
|
+
return isStateTreeNode(thing) && isBaseSession(thing)
|
|
129
|
+
}
|