@jbrowse/plugin-data-management 2.3.1 → 2.3.3

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.
Files changed (67) hide show
  1. package/dist/AddConnectionWidget/index.d.ts +3 -2
  2. package/dist/AddConnectionWidget/index.js +38 -4
  3. package/dist/AddConnectionWidget/index.js.map +1 -1
  4. package/dist/AddTrackWidget/index.d.ts +3 -2
  5. package/dist/AddTrackWidget/index.js +38 -4
  6. package/dist/AddTrackWidget/index.js.map +1 -1
  7. package/dist/HierarchicalTrackSelectorWidget/index.d.ts +3 -0
  8. package/dist/HierarchicalTrackSelectorWidget/index.js +36 -0
  9. package/dist/HierarchicalTrackSelectorWidget/index.js.map +1 -1
  10. package/dist/PluginStoreWidget/index.d.ts +3 -2
  11. package/dist/PluginStoreWidget/index.js +38 -4
  12. package/dist/PluginStoreWidget/index.js.map +1 -1
  13. package/dist/index.js +10 -51
  14. package/dist/index.js.map +1 -1
  15. package/dist/ucsc-trackhub/index.d.ts +3 -2
  16. package/dist/ucsc-trackhub/index.js +13 -5
  17. package/dist/ucsc-trackhub/index.js.map +1 -1
  18. package/dist/ucsc-trackhub/model.js +11 -17
  19. package/dist/ucsc-trackhub/model.js.map +1 -1
  20. package/dist/ucsc-trackhub/ucscTrackHub.d.ts +23 -5
  21. package/dist/ucsc-trackhub/ucscTrackHub.js +90 -143
  22. package/dist/ucsc-trackhub/ucscTrackHub.js.map +1 -1
  23. package/esm/AddConnectionWidget/index.d.ts +3 -2
  24. package/esm/AddConnectionWidget/index.js +15 -2
  25. package/esm/AddConnectionWidget/index.js.map +1 -1
  26. package/esm/AddTrackWidget/index.d.ts +3 -2
  27. package/esm/AddTrackWidget/index.js +15 -2
  28. package/esm/AddTrackWidget/index.js.map +1 -1
  29. package/esm/HierarchicalTrackSelectorWidget/index.d.ts +3 -0
  30. package/esm/HierarchicalTrackSelectorWidget/index.js +13 -0
  31. package/esm/HierarchicalTrackSelectorWidget/index.js.map +1 -1
  32. package/esm/PluginStoreWidget/index.d.ts +3 -2
  33. package/esm/PluginStoreWidget/index.js +15 -2
  34. package/esm/PluginStoreWidget/index.js.map +1 -1
  35. package/esm/index.js +10 -51
  36. package/esm/index.js.map +1 -1
  37. package/esm/ucsc-trackhub/index.d.ts +3 -2
  38. package/esm/ucsc-trackhub/index.js +13 -2
  39. package/esm/ucsc-trackhub/index.js.map +1 -1
  40. package/esm/ucsc-trackhub/model.js +11 -17
  41. package/esm/ucsc-trackhub/model.js.map +1 -1
  42. package/esm/ucsc-trackhub/ucscTrackHub.d.ts +23 -5
  43. package/esm/ucsc-trackhub/ucscTrackHub.js +87 -143
  44. package/esm/ucsc-trackhub/ucscTrackHub.js.map +1 -1
  45. package/package.json +2 -2
  46. package/src/AddConnectionWidget/components/{AddConnectionWidget.test.js → AddConnectionWidget.test.tsx} +17 -8
  47. package/src/AddConnectionWidget/components/__snapshots__/{AddConnectionWidget.test.js.snap → AddConnectionWidget.test.tsx.snap} +0 -0
  48. package/src/AddConnectionWidget/index.ts +17 -2
  49. package/src/AddTrackWidget/{index.test.jsx → index.test.tsx} +34 -37
  50. package/src/AddTrackWidget/index.ts +17 -2
  51. package/src/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.test.tsx +124 -128
  52. package/src/HierarchicalTrackSelectorWidget/components/__snapshots__/HierarchicalTrackSelector.test.tsx.snap +5 -5
  53. package/src/HierarchicalTrackSelectorWidget/index.ts +17 -0
  54. package/src/PluginStoreWidget/components/PluginStoreWidget.test.tsx +132 -0
  55. package/src/PluginStoreWidget/components/__snapshots__/{PluginStoreWidget.test.js.snap → PluginStoreWidget.test.tsx.snap} +2 -2
  56. package/src/PluginStoreWidget/index.ts +17 -2
  57. package/src/PluginStoreWidget/{model.test.js → model.test.tsx} +0 -0
  58. package/src/__snapshots__/index.test.ts.snap +9 -0
  59. package/src/index.test.ts +54 -0
  60. package/src/index.ts +10 -83
  61. package/src/ucsc-trackhub/index.ts +19 -2
  62. package/src/ucsc-trackhub/model.ts +15 -26
  63. package/src/ucsc-trackhub/ucscTrackHub.ts +326 -0
  64. package/src/PluginStoreWidget/components/PluginStoreWidget.test.js +0 -123
  65. package/src/__snapshots__/index.test.js.snap +0 -9
  66. package/src/index.test.js +0 -61
  67. package/src/ucsc-trackhub/ucscTrackHub.js +0 -442
@@ -0,0 +1,132 @@
1
+ import React from 'react'
2
+ import { getSnapshot, getParent } from 'mobx-state-tree'
3
+ import { ThemeProvider } from '@mui/material/styles'
4
+ import { render, cleanup, fireEvent, waitFor } from '@testing-library/react'
5
+ import { createJBrowseTheme } from '@jbrowse/core/ui'
6
+ import { createTestSession } from '@jbrowse/web/src/rootModel'
7
+
8
+ // locals
9
+ import PluginStoreWidget from './PluginStoreWidget'
10
+ import { PluginStoreModel } from '../model'
11
+
12
+ jest.mock('@jbrowse/web/src/makeWorkerInstance', () => () => {})
13
+
14
+ const plugins = {
15
+ plugins: [
16
+ {
17
+ name: 'MsaView',
18
+ authors: ['Colin Diesh'],
19
+ description: 'multiple sequence alignment browser plugin for JBrowse 2',
20
+ location: 'https://github.com/GMOD/jbrowse-plugin-msaview',
21
+ url: 'https://unpkg.com/jbrowse-plugin-msaview/dist/jbrowse-plugin-msaview.umd.production.min.js',
22
+ license: 'Apache License 2.0',
23
+ image:
24
+ 'https://raw.githubusercontent.com/GMOD/jbrowse-plugin-list/main/img/msaview-screenshot-fs8.png',
25
+ },
26
+ ],
27
+ }
28
+
29
+ let session: ReturnType<typeof createTestSession>
30
+ let model: PluginStoreModel
31
+
32
+ beforeEach(() => {
33
+ session = createTestSession()
34
+ model = session.addWidget('PluginStoreWidget', 'pluginStoreWidget')
35
+ const { location } = window
36
+
37
+ // @ts-ignore
38
+ delete window.location
39
+ window.location = {
40
+ ...location,
41
+ reload: jest.fn(),
42
+ }
43
+
44
+ // @ts-ignore
45
+ fetch.resetMocks()
46
+
47
+ // @ts-ignore
48
+ fetch.mockResponse(JSON.stringify(plugins))
49
+ })
50
+
51
+ afterEach(cleanup)
52
+
53
+ test('renders with the available plugins', async () => {
54
+ const { container, findByText } = render(
55
+ <ThemeProvider theme={createJBrowseTheme()}>
56
+ <PluginStoreWidget model={model} />
57
+ </ThemeProvider>,
58
+ )
59
+ await findByText('multiple sequence alignment browser plugin for JBrowse 2')
60
+ expect(container.firstChild).toMatchSnapshot()
61
+ })
62
+
63
+ test('Installs a session plugin', async () => {
64
+ const { findByText } = render(
65
+ <ThemeProvider theme={createJBrowseTheme()}>
66
+ <PluginStoreWidget model={model} />
67
+ </ThemeProvider>,
68
+ )
69
+ await findByText('multiple sequence alignment browser plugin for JBrowse 2')
70
+ fireEvent.click(await findByText('Install'))
71
+ await waitFor(() => {
72
+ expect(window.location.reload).toHaveBeenCalled()
73
+ })
74
+ expect(getSnapshot(session.sessionPlugins)[0]).toEqual(plugins.plugins[0])
75
+ })
76
+
77
+ test('plugin store admin - adds a custom plugin correctly', async () => {
78
+ session = createTestSession({}, true)
79
+ model = session.addWidget('PluginStoreWidget', 'pluginStoreWidget')
80
+ const { findByText, getByText, getByLabelText } = render(
81
+ <ThemeProvider theme={createJBrowseTheme()}>
82
+ <PluginStoreWidget model={model} />
83
+ </ThemeProvider>,
84
+ )
85
+ await findByText('multiple sequence alignment browser plugin for JBrowse 2')
86
+ fireEvent.click(getByText('Add custom plugin'))
87
+ fireEvent.change(getByLabelText('Plugin URL'), {
88
+ target: {
89
+ value:
90
+ 'https://unpkg.com/jbrowse-plugin-msaview/dist/jbrowse-plugin-msaview.esm.js',
91
+ },
92
+ })
93
+ fireEvent.change(getByLabelText('Plugin name'), {
94
+ target: {
95
+ value: 'MsaView',
96
+ },
97
+ })
98
+ fireEvent.click(getByText('Submit'))
99
+
100
+ await waitFor(() => {
101
+ expect(window.location.reload).toHaveBeenCalled()
102
+ })
103
+
104
+ expect(getSnapshot(getParent(session)).jbrowse.plugins).toEqual([
105
+ {
106
+ name: 'MsaView',
107
+ umdUrl:
108
+ 'https://unpkg.com/jbrowse-plugin-msaview/dist/jbrowse-plugin-msaview.esm.js',
109
+ },
110
+ ])
111
+ })
112
+
113
+ test('plugin store admin - removes a custom plugin correctly', async () => {
114
+ session = createTestSession({}, true)
115
+ model = session.addWidget('PluginStoreWidget', 'pluginStoreWidget')
116
+
117
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
+ const rootModel = getParent<any>(session)
119
+ const { jbrowse } = rootModel
120
+ jbrowse.addPlugin(plugins.plugins[0])
121
+ const { findByText, getByText, getByTestId } = render(
122
+ <ThemeProvider theme={createJBrowseTheme()}>
123
+ <PluginStoreWidget model={model} />
124
+ </ThemeProvider>,
125
+ )
126
+ await findByText('multiple sequence alignment browser plugin for JBrowse 2')
127
+ fireEvent.click(getByTestId('removePlugin-SVGPlugin'))
128
+ fireEvent.click(getByText('Confirm'))
129
+ await waitFor(() => {
130
+ expect(window.location.reload).toHaveBeenCalled()
131
+ })
132
+ })
@@ -1,6 +1,6 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`<PluginStoreWidget /> renders with the available plugins 1`] = `
3
+ exports[`renders with the available plugins 1`] = `
4
4
  <div
5
5
  class="css-1kq0gb6-root"
6
6
  >
@@ -16,7 +16,7 @@ exports[`<PluginStoreWidget /> renders with the available plugins 1`] = `
16
16
  Filter plugins
17
17
  </label>
18
18
  <div
19
- class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-sizeSmall MuiInputBase-adornedEnd css-1wz39fi-MuiInputBase-root-MuiInput-root"
19
+ class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-sizeSmall MuiInputBase-adornedEnd css-1blad95-MuiInputBase-root-MuiInput-root"
20
20
  >
21
21
  <input
22
22
  aria-invalid="false"
@@ -1,4 +1,19 @@
1
1
  import { ConfigurationSchema } from '@jbrowse/core/configuration'
2
+ import { WidgetType } from '@jbrowse/core/pluggableElementTypes'
3
+ import PluginManager from '@jbrowse/core/PluginManager'
4
+ import { lazy } from 'react'
2
5
 
3
- export { default as stateModelFactory } from './model'
4
- export const configSchema = ConfigurationSchema('PluginStoreWidget', {})
6
+ import stateModelFactory from './model'
7
+ const configSchema = ConfigurationSchema('PluginStoreWidget', {})
8
+
9
+ export default (pluginManager: PluginManager) => {
10
+ pluginManager.addWidgetType(() => {
11
+ return new WidgetType({
12
+ name: 'PluginStoreWidget',
13
+ heading: 'Plugin store',
14
+ configSchema,
15
+ stateModel: stateModelFactory(pluginManager),
16
+ ReactComponent: lazy(() => import('./components/PluginStoreWidget')),
17
+ })
18
+ })
19
+ }
@@ -0,0 +1,9 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`adds config editor widget 1`] = `{}`;
4
+
5
+ exports[`adds connection add widget 1`] = `{}`;
6
+
7
+ exports[`adds hierarchical track selector 1`] = `{}`;
8
+
9
+ exports[`adds track add widget 1`] = `{}`;
@@ -0,0 +1,54 @@
1
+ import PluginManager from '@jbrowse/core/PluginManager'
2
+ import Config from '@jbrowse/plugin-config'
3
+ import { getSnapshot } from 'mobx-state-tree'
4
+ import ThisPlugin from '.'
5
+
6
+ let pluginManager: PluginManager
7
+
8
+ beforeAll(() => {
9
+ pluginManager = new PluginManager([new ThisPlugin(), new Config()])
10
+ pluginManager.createPluggableElements()
11
+ pluginManager.configure()
12
+ })
13
+
14
+ test("won't add if already added", () => {
15
+ expect(() => pluginManager.addPlugin(new ThisPlugin())).toThrow(
16
+ /JBrowse already configured, cannot add plugins/,
17
+ )
18
+ })
19
+
20
+ test('adds track add widget', () => {
21
+ const AddTrackWidget = pluginManager.getWidgetType('AddTrackWidget')
22
+ const config = AddTrackWidget.configSchema.create({
23
+ type: 'AddTrackWidget',
24
+ })
25
+ expect(getSnapshot(config)).toMatchSnapshot()
26
+ })
27
+
28
+ test('adds config editor widget', () => {
29
+ const ConfigurationEditorWidget = pluginManager.getWidgetType(
30
+ 'ConfigurationEditorWidget',
31
+ )
32
+ const config = ConfigurationEditorWidget.configSchema.create({
33
+ type: 'ConfigurationEditorWidget',
34
+ })
35
+ expect(getSnapshot(config)).toMatchSnapshot()
36
+ })
37
+
38
+ test('adds connection add widget', () => {
39
+ const AddConnectionWidget = pluginManager.getWidgetType('AddConnectionWidget')
40
+ const config = AddConnectionWidget.configSchema.create({
41
+ type: 'AddConnectionWidget',
42
+ })
43
+ expect(getSnapshot(config)).toMatchSnapshot()
44
+ })
45
+
46
+ test('adds hierarchical track selector', () => {
47
+ const HierarchicalTrackSelectorWidget = pluginManager.getWidgetType(
48
+ 'HierarchicalTrackSelectorWidget',
49
+ )
50
+ const config = HierarchicalTrackSelectorWidget.configSchema.create({
51
+ type: 'HierarchicalTrackSelectorWidget',
52
+ })
53
+ expect(getSnapshot(config)).toMatchSnapshot()
54
+ })
package/src/index.ts CHANGED
@@ -1,30 +1,14 @@
1
1
  import { lazy } from 'react'
2
- import ConnectionType from '@jbrowse/core/pluggableElementTypes/ConnectionType'
3
- import WidgetType from '@jbrowse/core/pluggableElementTypes/WidgetType'
4
2
  import Plugin from '@jbrowse/core/Plugin'
5
3
  import PluginManager from '@jbrowse/core/PluginManager'
6
- import {
7
- configSchema as ucscConfigSchema,
8
- modelFactory as ucscModelFactory,
9
- } from './ucsc-trackhub'
10
- import {
11
- stateModelFactory as AddTrackStateModelFactory,
12
- configSchema as AddTrackConfigSchema,
13
- } from './AddTrackWidget'
4
+ import UCSCTrackHubConnectionF from './ucsc-trackhub'
5
+ import AddTrackWidgetF from './AddTrackWidget'
14
6
  import { AddTrackModel } from './AddTrackWidget/model'
15
- import {
16
- stateModel as AddConnectionStateModel,
17
- configSchema as AddConnectionConfigSchema,
18
- } from './AddConnectionWidget'
19
- import {
20
- stateModelFactory as HierarchicalTrackSelectorStateModelFactory,
21
- configSchema as HierarchicalTrackSelectorConfigSchema,
7
+ import AddConnectionWidgetF from './AddConnectionWidget'
8
+ import PluginStoreWidgetF from './PluginStoreWidget'
9
+ import HierarchicalTrackSelectorWidgetF, {
22
10
  HierarchicalTrackSelectorModel,
23
11
  } from './HierarchicalTrackSelectorWidget'
24
- import {
25
- stateModelFactory as PluginStoreStateModelFactory,
26
- configSchema as PluginStoreConfigSchema,
27
- } from './PluginStoreWidget'
28
12
 
29
13
  const SetDefaultSession = lazy(() => import('./SetDefaultSession'))
30
14
 
@@ -39,68 +23,11 @@ export default class extends Plugin {
39
23
  }
40
24
 
41
25
  install(pluginManager: PluginManager) {
42
- pluginManager.addConnectionType(
43
- () =>
44
- new ConnectionType({
45
- name: 'UCSCTrackHubConnection',
46
- configSchema: ucscConfigSchema,
47
- stateModel: ucscModelFactory(pluginManager),
48
- displayName: 'UCSC Track Hub',
49
- description: 'A track or assembly hub in the Track Hub format',
50
- url: '//genome.ucsc.edu/goldenPath/help/hgTrackHubHelp.html#Intro',
51
- }),
52
- )
53
-
54
- pluginManager.addWidgetType(() => {
55
- return new WidgetType({
56
- name: 'HierarchicalTrackSelectorWidget',
57
- heading: 'Available tracks',
58
- configSchema: HierarchicalTrackSelectorConfigSchema,
59
- stateModel: HierarchicalTrackSelectorStateModelFactory(pluginManager),
60
- ReactComponent: lazy(
61
- () =>
62
- import(
63
- './HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector'
64
- ),
65
- ),
66
- })
67
- })
68
-
69
- pluginManager.addWidgetType(() => {
70
- return new WidgetType({
71
- name: 'AddTrackWidget',
72
- heading: 'Add a track',
73
- configSchema: AddTrackConfigSchema,
74
- stateModel: AddTrackStateModelFactory(pluginManager),
75
- ReactComponent: lazy(
76
- () => import('./AddTrackWidget/components/AddTrackWidget'),
77
- ),
78
- })
79
- })
80
-
81
- pluginManager.addWidgetType(() => {
82
- return new WidgetType({
83
- name: 'AddConnectionWidget',
84
- heading: 'Add a connection',
85
- configSchema: AddConnectionConfigSchema,
86
- stateModel: AddConnectionStateModel,
87
- ReactComponent: lazy(
88
- () => import('./AddConnectionWidget/components/AddConnectionWidget'),
89
- ),
90
- })
91
- })
92
-
93
- pluginManager.addWidgetType(() => {
94
- return new WidgetType({
95
- name: 'PluginStoreWidget',
96
- heading: 'Plugin store',
97
- configSchema: PluginStoreConfigSchema,
98
- stateModel: PluginStoreStateModelFactory(pluginManager),
99
- ReactComponent: lazy(
100
- () => import('./PluginStoreWidget/components/PluginStoreWidget'),
101
- ),
102
- })
103
- })
26
+ UCSCTrackHubConnectionF(pluginManager)
27
+ AddTrackWidgetF(pluginManager)
28
+ HierarchicalTrackSelectorWidgetF(pluginManager)
29
+ AddConnectionWidgetF(pluginManager)
30
+ PluginStoreWidgetF(pluginManager)
104
31
  }
105
32
 
106
33
  configure(_pluginManager: PluginManager) {}
@@ -1,2 +1,19 @@
1
- export { default as modelFactory } from './model'
2
- export { default as configSchema } from './configSchema'
1
+ import { ConnectionType } from '@jbrowse/core/pluggableElementTypes'
2
+ import PluginManager from '@jbrowse/core/PluginManager'
3
+
4
+ import stateModelFactory from './model'
5
+ import configSchema from './configSchema'
6
+
7
+ export default (pluginManager: PluginManager) => {
8
+ pluginManager.addConnectionType(
9
+ () =>
10
+ new ConnectionType({
11
+ name: 'UCSCTrackHubConnection',
12
+ configSchema,
13
+ stateModel: stateModelFactory(pluginManager),
14
+ displayName: 'UCSC Track Hub',
15
+ description: 'A track or assembly hub in the Track Hub format',
16
+ url: '//genome.ucsc.edu/goldenPath/help/hgTrackHubHelp.html#Intro',
17
+ }),
18
+ )
19
+ }
@@ -43,11 +43,11 @@ export default function UCSCTrackHubConnection(pluginManager: PluginManager) {
43
43
  const genomesFileLocation = hubUri
44
44
  ? {
45
45
  uri: new URL(genomeFile, hubUri).href,
46
- locationType: 'UriLocation',
46
+ locationType: 'UriLocation' as const,
47
47
  }
48
48
  : {
49
49
  localPath: genomeFile,
50
- locationType: 'LocalPathLocation',
50
+ locationType: 'LocalPathLocation' as const,
51
51
  }
52
52
  const genomesFile = await fetchGenomesFile(genomesFileLocation)
53
53
  const trackDbData = []
@@ -67,43 +67,32 @@ export default function UCSCTrackHubConnection(pluginManager: PluginManager) {
67
67
  `Cannot find assembly for "${genomeName}" from the genomes file for connection "${connectionName}"`,
68
68
  )
69
69
  }
70
- const trackDb = genome.get('trackDb')
71
- if (!trackDb) {
70
+ const db = genome.get('trackDb')
71
+ if (!db) {
72
72
  throw new Error('genomesFile not found on hub')
73
73
  }
74
- const trackDbFileLocation = hubUri
74
+ const base = new URL(genomeFile, hubUri)
75
+ const trackDbLoc = hubUri
75
76
  ? {
76
- uri: new URL(trackDb, new URL(genomeFile, hubUri)).href,
77
- locationType: 'UriLocation',
77
+ uri: new URL(db, base).href,
78
+ locationType: 'UriLocation' as const,
78
79
  }
79
80
  : {
80
- localPath: trackDb,
81
- locationType: 'LocalPathLocation',
81
+ localPath: db,
82
+ locationType: 'LocalPathLocation' as const,
82
83
  }
83
- trackDbData.push([
84
- trackDbFileLocation,
85
- await fetchTrackDbFile(trackDbFileLocation),
86
- genomeName,
87
- conf,
88
- ] as const)
84
+ const trackDb = await fetchTrackDbFile(trackDbLoc)
85
+ trackDbData.push([trackDbLoc, trackDb, genomeName, conf] as const)
89
86
  }
90
87
  for (const [
91
- trackDbFileLocation,
88
+ trackDbLoc,
92
89
  trackDbFile,
93
90
  genomeName,
94
91
  conf,
95
92
  ] of trackDbData) {
96
- const sequenceAdapter = readConfObject(conf, [
97
- 'sequence',
98
- 'adapter',
99
- ])
93
+ const seqAdapter = readConfObject(conf, ['sequence', 'adapter'])
100
94
  self.addTrackConfs(
101
- generateTracks(
102
- trackDbFile,
103
- trackDbFileLocation,
104
- genomeName,
105
- sequenceAdapter,
106
- ),
95
+ generateTracks(trackDbFile, trackDbLoc, genomeName, seqAdapter),
107
96
  )
108
97
  }
109
98
  } catch (e) {