@jbrowse/plugin-data-management 2.6.2 → 2.7.0

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 (161) hide show
  1. package/dist/AddConnectionWidget/components/AddConnectionWidget.d.ts +2 -2
  2. package/dist/AddConnectionWidget/components/AddConnectionWidget.js +17 -8
  3. package/dist/AddConnectionWidget/components/ConfigureConnection.d.ts +2 -2
  4. package/dist/AddConnectionWidget/components/ConfigureConnection.js +2 -1
  5. package/dist/AddConnectionWidget/components/ConnectionTypeSelect.d.ts +2 -2
  6. package/dist/AddConnectionWidget/components/ConnectionTypeSelect.js +5 -3
  7. package/dist/AddTrackWidget/components/AddTrackWidget.d.ts +3 -4
  8. package/dist/AddTrackWidget/components/AddTrackWidget.js +3 -3
  9. package/dist/AddTrackWidget/components/ConfirmTrack.d.ts +2 -2
  10. package/dist/AddTrackWidget/components/ConfirmTrack.js +3 -2
  11. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.d.ts +3 -4
  12. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.js +32 -27
  13. package/dist/AddTrackWidget/components/PasteConfigWorkflow.d.ts +3 -4
  14. package/dist/AddTrackWidget/components/PasteConfigWorkflow.js +10 -7
  15. package/dist/AddTrackWidget/components/TrackAdapterSelector.js +1 -1
  16. package/dist/AddTrackWidget/components/TrackSourceSelect.d.ts +3 -4
  17. package/dist/AddTrackWidget/components/TrackSourceSelect.js +3 -3
  18. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalFab.d.ts +2 -2
  19. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalFab.js +2 -1
  20. package/dist/HierarchicalTrackSelectorWidget/components/ShoppingCart.d.ts +2 -2
  21. package/dist/HierarchicalTrackSelectorWidget/components/ShoppingCart.js +2 -1
  22. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.d.ts +3 -5
  23. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.js +2 -1
  24. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/DeleteConnectionDialog.d.ts +3 -4
  25. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/DeleteConnectionDialog.js +5 -8
  26. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ManageConnectionsDialog.d.ts +3 -4
  27. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ManageConnectionsDialog.js +3 -3
  28. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.d.ts +2 -3
  29. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.js +2 -3
  30. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilter.d.ts +13 -0
  31. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilter.js +72 -0
  32. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js +31 -77
  33. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.d.ts +3 -4
  34. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.js +3 -3
  35. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.d.ts +5 -3
  36. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js +10 -4
  37. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.d.ts +2 -2
  38. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +53 -33
  39. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.d.ts +2 -2
  40. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +39 -21
  41. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.d.ts +3 -4
  42. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +13 -9
  43. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.d.ts +4 -3
  44. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js +5 -6
  45. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js +22 -0
  46. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js +3 -3
  47. package/dist/HierarchicalTrackSelectorWidget/components/util.d.ts +2 -1
  48. package/dist/HierarchicalTrackSelectorWidget/components/util.js +1 -2
  49. package/dist/HierarchicalTrackSelectorWidget/filterTracks.d.ts +12 -0
  50. package/dist/HierarchicalTrackSelectorWidget/filterTracks.js +32 -0
  51. package/dist/HierarchicalTrackSelectorWidget/generateHierarchy.d.ts +21 -0
  52. package/dist/HierarchicalTrackSelectorWidget/generateHierarchy.js +98 -0
  53. package/dist/HierarchicalTrackSelectorWidget/model.d.ts +68 -28
  54. package/dist/HierarchicalTrackSelectorWidget/model.js +147 -117
  55. package/dist/HierarchicalTrackSelectorWidget/util.d.ts +12 -0
  56. package/dist/HierarchicalTrackSelectorWidget/util.js +53 -0
  57. package/dist/PluginStoreWidget/components/AddCustomPluginDialog.d.ts +7 -0
  58. package/dist/PluginStoreWidget/components/{CustomPluginForm.js → AddCustomPluginDialog.js} +13 -21
  59. package/dist/PluginStoreWidget/components/DeletePluginDialog.d.ts +5 -0
  60. package/dist/PluginStoreWidget/components/DeletePluginDialog.js +28 -0
  61. package/dist/PluginStoreWidget/components/InstalledPlugin.d.ts +3 -6
  62. package/dist/PluginStoreWidget/components/InstalledPlugin.js +24 -51
  63. package/dist/PluginStoreWidget/components/InstalledPluginsList.d.ts +3 -4
  64. package/dist/PluginStoreWidget/components/InstalledPluginsList.js +7 -9
  65. package/dist/PluginStoreWidget/components/PluginCard.d.ts +2 -2
  66. package/dist/PluginStoreWidget/components/PluginCard.js +5 -6
  67. package/dist/PluginStoreWidget/components/PluginStoreWidget.d.ts +3 -4
  68. package/dist/PluginStoreWidget/components/PluginStoreWidget.js +14 -42
  69. package/dist/PluginStoreWidget/components/util.d.ts +5 -0
  70. package/dist/PluginStoreWidget/components/util.js +29 -0
  71. package/dist/PluginStoreWidget/model.d.ts +2 -2
  72. package/dist/PluginStoreWidget/model.js +2 -2
  73. package/dist/index.d.ts +1 -9
  74. package/dist/index.js +1 -4
  75. package/dist/ucsc-trackhub/model.js +2 -2
  76. package/esm/AddConnectionWidget/components/AddConnectionWidget.d.ts +2 -2
  77. package/esm/AddConnectionWidget/components/AddConnectionWidget.js +19 -10
  78. package/esm/AddConnectionWidget/components/ConfigureConnection.d.ts +2 -2
  79. package/esm/AddConnectionWidget/components/ConfigureConnection.js +2 -1
  80. package/esm/AddConnectionWidget/components/ConnectionTypeSelect.d.ts +2 -2
  81. package/esm/AddConnectionWidget/components/ConnectionTypeSelect.js +5 -3
  82. package/esm/AddTrackWidget/components/AddTrackWidget.d.ts +3 -4
  83. package/esm/AddTrackWidget/components/AddTrackWidget.js +3 -3
  84. package/esm/AddTrackWidget/components/ConfirmTrack.d.ts +2 -2
  85. package/esm/AddTrackWidget/components/ConfirmTrack.js +4 -3
  86. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.d.ts +3 -4
  87. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.js +33 -28
  88. package/esm/AddTrackWidget/components/PasteConfigWorkflow.d.ts +3 -4
  89. package/esm/AddTrackWidget/components/PasteConfigWorkflow.js +11 -8
  90. package/esm/AddTrackWidget/components/TrackAdapterSelector.js +1 -1
  91. package/esm/AddTrackWidget/components/TrackSourceSelect.d.ts +3 -4
  92. package/esm/AddTrackWidget/components/TrackSourceSelect.js +3 -3
  93. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalFab.d.ts +2 -2
  94. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalFab.js +2 -1
  95. package/esm/HierarchicalTrackSelectorWidget/components/ShoppingCart.d.ts +2 -2
  96. package/esm/HierarchicalTrackSelectorWidget/components/ShoppingCart.js +2 -1
  97. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.d.ts +3 -5
  98. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.js +2 -1
  99. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/DeleteConnectionDialog.d.ts +3 -4
  100. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/DeleteConnectionDialog.js +6 -9
  101. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ManageConnectionsDialog.d.ts +3 -4
  102. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ManageConnectionsDialog.js +3 -3
  103. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.d.ts +2 -3
  104. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.js +3 -2
  105. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilter.d.ts +13 -0
  106. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilter.js +43 -0
  107. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js +31 -54
  108. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.d.ts +3 -4
  109. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.js +3 -3
  110. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.d.ts +5 -3
  111. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js +10 -4
  112. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.d.ts +2 -2
  113. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +51 -31
  114. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.d.ts +2 -2
  115. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +38 -20
  116. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.d.ts +3 -4
  117. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +13 -9
  118. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.d.ts +4 -3
  119. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js +5 -6
  120. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js +22 -0
  121. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js +2 -2
  122. package/esm/HierarchicalTrackSelectorWidget/components/util.d.ts +2 -1
  123. package/esm/HierarchicalTrackSelectorWidget/components/util.js +1 -2
  124. package/esm/HierarchicalTrackSelectorWidget/filterTracks.d.ts +12 -0
  125. package/esm/HierarchicalTrackSelectorWidget/filterTracks.js +28 -0
  126. package/esm/HierarchicalTrackSelectorWidget/generateHierarchy.d.ts +21 -0
  127. package/esm/HierarchicalTrackSelectorWidget/generateHierarchy.js +94 -0
  128. package/esm/HierarchicalTrackSelectorWidget/model.d.ts +68 -28
  129. package/esm/HierarchicalTrackSelectorWidget/model.js +149 -116
  130. package/esm/HierarchicalTrackSelectorWidget/util.d.ts +12 -0
  131. package/esm/HierarchicalTrackSelectorWidget/util.js +45 -0
  132. package/esm/PluginStoreWidget/components/AddCustomPluginDialog.d.ts +7 -0
  133. package/esm/PluginStoreWidget/components/{CustomPluginForm.js → AddCustomPluginDialog.js} +13 -21
  134. package/esm/PluginStoreWidget/components/DeletePluginDialog.d.ts +5 -0
  135. package/esm/PluginStoreWidget/components/DeletePluginDialog.js +22 -0
  136. package/esm/PluginStoreWidget/components/InstalledPlugin.d.ts +3 -6
  137. package/esm/PluginStoreWidget/components/InstalledPlugin.js +27 -54
  138. package/esm/PluginStoreWidget/components/InstalledPluginsList.d.ts +3 -4
  139. package/esm/PluginStoreWidget/components/InstalledPluginsList.js +7 -9
  140. package/esm/PluginStoreWidget/components/PluginCard.d.ts +2 -2
  141. package/esm/PluginStoreWidget/components/PluginCard.js +5 -6
  142. package/esm/PluginStoreWidget/components/PluginStoreWidget.d.ts +3 -4
  143. package/esm/PluginStoreWidget/components/PluginStoreWidget.js +15 -43
  144. package/esm/PluginStoreWidget/components/util.d.ts +5 -0
  145. package/esm/PluginStoreWidget/components/util.js +25 -0
  146. package/esm/PluginStoreWidget/model.d.ts +2 -2
  147. package/esm/PluginStoreWidget/model.js +1 -1
  148. package/esm/index.d.ts +1 -9
  149. package/esm/index.js +1 -3
  150. package/esm/ucsc-trackhub/model.js +2 -2
  151. package/package.json +5 -4
  152. package/dist/PluginStoreWidget/components/CustomPluginForm.d.ts +0 -9
  153. package/dist/SetDefaultSession/SetDefaultSession.d.ts +0 -6
  154. package/dist/SetDefaultSession/SetDefaultSession.js +0 -38
  155. package/dist/SetDefaultSession/index.d.ts +0 -1
  156. package/dist/SetDefaultSession/index.js +0 -8
  157. package/esm/PluginStoreWidget/components/CustomPluginForm.d.ts +0 -9
  158. package/esm/SetDefaultSession/SetDefaultSession.d.ts +0 -6
  159. package/esm/SetDefaultSession/SetDefaultSession.js +0 -33
  160. package/esm/SetDefaultSession/index.d.ts +0 -1
  161. package/esm/SetDefaultSession/index.js +0 -1
@@ -1,19 +1,7 @@
1
1
  import { Instance } from 'mobx-state-tree';
2
2
  import { AnyConfigurationModel } from '@jbrowse/core/configuration';
3
- import { AbstractSessionModel } from '@jbrowse/core/util';
4
3
  import PluginManager from '@jbrowse/core/PluginManager';
5
- export declare function matches(query: string, conf: AnyConfigurationModel, session: AbstractSessionModel): boolean;
6
- export type TreeNode = {
7
- name: string;
8
- id: string;
9
- conf?: AnyConfigurationModel;
10
- checked?: boolean;
11
- isOpenByDefault?: boolean;
12
- children: TreeNode[];
13
- };
14
- export declare function generateHierarchy(model: HierarchicalTrackSelectorModel, trackConfigurations: AnyConfigurationModel[], collapsed: {
15
- get: (arg: string) => boolean | undefined;
16
- }, extra?: string): TreeNode[];
4
+ import { TreeNode } from './generateHierarchy';
17
5
  /**
18
6
  * #stateModel HierarchicalTrackSelectorWidget
19
7
  */
@@ -26,10 +14,22 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
26
14
  * #property
27
15
  */
28
16
  type: import("mobx-state-tree").ISimpleType<"HierarchicalTrackSelectorWidget">;
17
+ /**
18
+ * #property
19
+ */
20
+ initialized: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<boolean>>;
29
21
  /**
30
22
  * #property
31
23
  */
32
24
  collapsed: import("mobx-state-tree").IMapType<import("mobx-state-tree").ISimpleType<boolean>>;
25
+ /**
26
+ * #property
27
+ */
28
+ sortTrackNames: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<boolean>>;
29
+ /**
30
+ * #property
31
+ */
32
+ sortCategories: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<boolean>>;
33
33
  /**
34
34
  * #property
35
35
  */
@@ -42,6 +42,14 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
42
42
  } & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>)[];
43
43
  filterText: string;
44
44
  } & {
45
+ /**
46
+ * #action
47
+ */
48
+ setSortTrackNames(val: boolean): void;
49
+ /**
50
+ * #action
51
+ */
52
+ setSortCategories(val: boolean): void;
45
53
  /**
46
54
  * #action
47
55
  */
@@ -66,6 +74,14 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
66
74
  * #action
67
75
  */
68
76
  toggleCategory(pathName: string): void;
77
+ /**
78
+ * #action
79
+ */
80
+ setCategoryCollapsed(pathName: string, status: boolean): void;
81
+ /**
82
+ * #action
83
+ */
84
+ expandAllCategories(): void;
69
85
  /**
70
86
  * #action
71
87
  */
@@ -85,6 +101,14 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
85
101
  */
86
102
  readonly assemblyNames: string[];
87
103
  } & {
104
+ /**
105
+ * #getter
106
+ */
107
+ readonly activeSortTrackNames: any;
108
+ /**
109
+ * #getter
110
+ */
111
+ readonly activeSortCategories: any;
88
112
  /**
89
113
  * #method
90
114
  * filter out tracks that don't match the current display types
@@ -105,6 +129,23 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
105
129
  } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
106
130
  setSubschema(slotName: string, data: unknown): any;
107
131
  } & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>)[];
132
+ } & {
133
+ /**
134
+ * #method
135
+ */
136
+ connectionHierarchy(connection: {
137
+ name: string;
138
+ tracks: AnyConfigurationModel[];
139
+ }): TreeNode[];
140
+ } & {
141
+ readonly allTracks: {
142
+ group: any;
143
+ tracks: ({
144
+ [x: string]: any;
145
+ } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
146
+ setSubschema(slotName: string, data: unknown): any;
147
+ } & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>)[];
148
+ }[];
108
149
  } & {
109
150
  /**
110
151
  * #getter
@@ -112,26 +153,25 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
112
153
  readonly hierarchy: {
113
154
  name: string;
114
155
  id: string;
115
- children: ({
116
- id: any;
156
+ children: {
117
157
  name: any;
158
+ id: any;
118
159
  children: TreeNode[];
119
- state: {
120
- expanded: boolean;
121
- };
122
- } | {
123
- name: string;
124
- id: string;
125
- children: TreeNode[];
126
- })[];
160
+ }[];
127
161
  };
162
+ } & {
128
163
  /**
129
- * #method
164
+ * #action
130
165
  */
131
- connectionHierarchy(connection: {
132
- name: string;
133
- tracks: AnyConfigurationModel[];
134
- }): TreeNode[];
166
+ collapseSubCategories(): void;
167
+ /**
168
+ * #action
169
+ */
170
+ collapseTopLevelCategories(): void;
171
+ } & {
172
+ afterCreate(): void;
173
+ } & {
174
+ readonly hasAnySubcategories: boolean;
135
175
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
136
176
  export type HierarchicalTrackSelectorStateModel = ReturnType<typeof stateTreeFactory>;
137
177
  export type HierarchicalTrackSelectorModel = Instance<HierarchicalTrackSelectorStateModel>;
@@ -1,95 +1,11 @@
1
- import { types, getSnapshot } from 'mobx-state-tree';
1
+ import { types } from 'mobx-state-tree';
2
2
  import { getConf, readConfObject, } from '@jbrowse/core/configuration';
3
- import { dedupe, getSession, getEnv, notEmpty, } from '@jbrowse/core/util';
4
- import { getTrackName } from '@jbrowse/core/util/tracks';
3
+ import { dedupe, getSession, notEmpty } from '@jbrowse/core/util';
5
4
  import { ElementId } from '@jbrowse/core/util/types/mst';
6
- function hasAnyOverlap(a1 = [], a2 = []) {
7
- // shortcut case is that arrays are single entries, and are equal
8
- // long case is that we use a set
9
- if (a1[0] === a2[0]) {
10
- return true;
11
- }
12
- else {
13
- const s1 = new Set(a1);
14
- return a2.some(a => s1.has(a));
15
- }
16
- }
17
- export function matches(query, conf, session) {
18
- const categories = readConfObject(conf, 'category');
19
- const queryLower = query.toLowerCase();
20
- return (getTrackName(conf, session).toLowerCase().includes(queryLower) ||
21
- !!(categories === null || categories === void 0 ? void 0 : categories.filter(c => c.toLowerCase().includes(queryLower)).length));
22
- }
23
- function filterTracks(tracks, self) {
24
- const { assemblyManager } = getSession(self);
25
- const { pluginManager } = getEnv(self);
26
- const { view } = self;
27
- const { trackSelectorAnyOverlap } = view;
28
- const trackListAssemblies = self.assemblyNames
29
- .map(a => assemblyManager.get(a))
30
- .filter(notEmpty);
31
- return tracks
32
- .filter(c => {
33
- const trackAssemblyNames = readConfObject(c, 'assemblyNames');
34
- const trackAssemblies = new Set((trackAssemblyNames === null || trackAssemblyNames === void 0 ? void 0 : trackAssemblyNames.map(name => assemblyManager.get(name)).filter(notEmpty)) || []);
35
- return trackSelectorAnyOverlap
36
- ? trackListAssemblies.some(a => trackAssemblies.has(a))
37
- : trackListAssemblies.every(a => trackAssemblies.has(a));
38
- })
39
- .filter(c => {
40
- const { displayTypes } = pluginManager.getViewType(view.type);
41
- const compatDisplays = displayTypes.map(d => d.name);
42
- const trackDisplays = c.displays.map((d) => d.type);
43
- return hasAnyOverlap(compatDisplays, trackDisplays);
44
- });
45
- }
46
- export function generateHierarchy(model, trackConfigurations, collapsed, extra) {
47
- const hierarchy = { children: [] };
48
- const { filterText, view } = model;
49
- const session = getSession(model);
50
- trackConfigurations
51
- .filter(conf => matches(filterText, conf, session))
52
- .forEach(conf => {
53
- // copy the categories since this array can be mutated downstream
54
- const categories = [...(readConfObject(conf, 'category') || [])];
55
- // silly thing where if trackId ends with sessionTrack, then push it to
56
- // a category that starts with a space to force sort to the top...
57
- // double whammy hackyness
58
- if (conf.trackId.endsWith('sessionTrack')) {
59
- categories.unshift(' Session tracks');
60
- }
61
- let currLevel = hierarchy;
62
- // find existing category to put track into or create it
63
- for (let i = 0; i < categories.length; i++) {
64
- const category = categories[i];
65
- const ret = currLevel.children.find(c => c.name === category);
66
- const id = extra + '-' + categories.slice(0, i + 1).join(',');
67
- if (!ret) {
68
- const n = {
69
- children: [],
70
- name: category,
71
- id,
72
- isOpenByDefault: !collapsed.get(id),
73
- };
74
- currLevel.children.push(n);
75
- currLevel = n;
76
- }
77
- else {
78
- currLevel = ret;
79
- }
80
- }
81
- const tracks = view.tracks;
82
- // using splice here tries to group leaf nodes above hierarchical nodes
83
- currLevel.children.splice(currLevel.children.findIndex(elt => elt.children.length), 0, {
84
- id: conf.trackId,
85
- name: getTrackName(conf, session),
86
- conf,
87
- checked: tracks.some(f => f.configuration === conf),
88
- children: [],
89
- });
90
- });
91
- return hierarchy.children;
92
- }
5
+ // locals
6
+ import { filterTracks } from './filterTracks';
7
+ import { generateHierarchy } from './generateHierarchy';
8
+ import { findSubCategories, findTopLevelCategories } from './util';
93
9
  /**
94
10
  * #stateModel HierarchicalTrackSelectorWidget
95
11
  */
@@ -104,10 +20,22 @@ export default function stateTreeFactory(pluginManager) {
104
20
  * #property
105
21
  */
106
22
  type: types.literal('HierarchicalTrackSelectorWidget'),
23
+ /**
24
+ * #property
25
+ */
26
+ initialized: types.maybe(types.boolean),
107
27
  /**
108
28
  * #property
109
29
  */
110
30
  collapsed: types.map(types.boolean),
31
+ /**
32
+ * #property
33
+ */
34
+ sortTrackNames: types.maybe(types.boolean),
35
+ /**
36
+ * #property
37
+ */
38
+ sortCategories: types.maybe(types.boolean),
111
39
  /**
112
40
  * #property
113
41
  */
@@ -118,6 +46,18 @@ export default function stateTreeFactory(pluginManager) {
118
46
  filterText: '',
119
47
  }))
120
48
  .actions(self => ({
49
+ /**
50
+ * #action
51
+ */
52
+ setSortTrackNames(val) {
53
+ self.sortTrackNames = val;
54
+ },
55
+ /**
56
+ * #action
57
+ */
58
+ setSortCategories(val) {
59
+ self.sortCategories = val;
60
+ },
121
61
  /**
122
62
  * #action
123
63
  */
@@ -154,6 +94,18 @@ export default function stateTreeFactory(pluginManager) {
154
94
  toggleCategory(pathName) {
155
95
  self.collapsed.set(pathName, !self.collapsed.get(pathName));
156
96
  },
97
+ /**
98
+ * #action
99
+ */
100
+ setCategoryCollapsed(pathName, status) {
101
+ self.collapsed.set(pathName, status);
102
+ },
103
+ /**
104
+ * #action
105
+ */
106
+ expandAllCategories() {
107
+ self.collapsed.clear();
108
+ },
157
109
  /**
158
110
  * #action
159
111
  */
@@ -197,24 +149,59 @@ export default function stateTreeFactory(pluginManager) {
197
149
  },
198
150
  }))
199
151
  .views(self => ({
152
+ /**
153
+ * #getter
154
+ */
155
+ get activeSortTrackNames() {
156
+ var _a;
157
+ return ((_a = self.sortTrackNames) !== null && _a !== void 0 ? _a : getConf(getSession(self), ['hierarchical', 'sort', 'trackNames']));
158
+ },
159
+ /**
160
+ * #getter
161
+ */
162
+ get activeSortCategories() {
163
+ var _a;
164
+ return ((_a = self.sortCategories) !== null && _a !== void 0 ? _a : getConf(getSession(self), ['hierarchical', 'sort', 'categories']));
165
+ },
200
166
  /**
201
167
  * #method
202
168
  * filter out tracks that don't match the current display types
203
169
  */
204
170
  connectionTrackConfigurations(connection) {
205
- return !self.view ? [] : filterTracks(connection.tracks, self);
171
+ return filterTracks(connection.tracks, self);
206
172
  },
207
173
  /**
208
174
  * #getter
209
175
  * filter out tracks that don't match the current assembly/display types
210
176
  */
211
177
  get trackConfigurations() {
212
- return !self.view
213
- ? []
214
- : [
215
- ...self.assemblyNames.map(a => self.getRefSeqTrackConf(a)),
216
- ...filterTracks(getSession(self).tracks, self),
217
- ].filter(notEmpty);
178
+ return [
179
+ ...self.assemblyNames.map(a => self.getRefSeqTrackConf(a)),
180
+ ...filterTracks(getSession(self).tracks, self),
181
+ ].filter(notEmpty);
182
+ },
183
+ }))
184
+ .views(self => ({
185
+ /**
186
+ * #method
187
+ */
188
+ connectionHierarchy(connection) {
189
+ return generateHierarchy(self, self.connectionTrackConfigurations(connection), self.collapsed, connection.name);
190
+ },
191
+ }))
192
+ .views(self => ({
193
+ get allTracks() {
194
+ const { connectionInstances = [] } = getSession(self);
195
+ return [
196
+ {
197
+ group: 'Tracks',
198
+ tracks: self.trackConfigurations,
199
+ },
200
+ ...connectionInstances.flatMap(c => ({
201
+ group: getConf(c, 'name'),
202
+ tracks: c.tracks,
203
+ })),
204
+ ];
218
205
  },
219
206
  }))
220
207
  .views(self => ({
@@ -222,32 +209,78 @@ export default function stateTreeFactory(pluginManager) {
222
209
  * #getter
223
210
  */
224
211
  get hierarchy() {
225
- const hier = generateHierarchy(self, self.trackConfigurations, self.collapsed);
226
- const session = getSession(self);
227
- const { connectionInstances } = session;
228
- const conns = (connectionInstances === null || connectionInstances === void 0 ? void 0 : connectionInstances.map(c => ({
229
- // @ts-expect-error
230
- id: getSnapshot(c).configuration,
231
- name: getConf(c, 'name'),
232
- children: this.connectionHierarchy(c),
233
- state: {
234
- expanded: true,
235
- },
236
- })).filter(f => f.children.length)) || [];
237
212
  return {
238
213
  name: 'Root',
239
214
  id: 'Root',
240
- children: [
241
- { name: 'Tracks', id: 'Tracks', children: hier },
242
- ...conns,
243
- ],
215
+ children: self.allTracks
216
+ .map(s => ({
217
+ name: s.group,
218
+ id: s.group,
219
+ children: generateHierarchy(self, s.tracks, self.collapsed),
220
+ }))
221
+ // always keep the Tracks entry at idx 0
222
+ .filter((f, idx) => idx === 0 || !!f.children.length),
244
223
  };
245
224
  },
225
+ }))
226
+ .actions(self => ({
246
227
  /**
247
- * #method
228
+ * #action
248
229
  */
249
- connectionHierarchy(connection) {
250
- return generateHierarchy(self, self.connectionTrackConfigurations(connection), self.collapsed, connection.name);
230
+ collapseSubCategories() {
231
+ const paths = [];
232
+ findSubCategories(self.hierarchy.children, paths);
233
+ for (const path of paths) {
234
+ self.setCategoryCollapsed(path, true);
235
+ }
236
+ },
237
+ /**
238
+ * #action
239
+ */
240
+ collapseTopLevelCategories() {
241
+ const paths = [];
242
+ for (const trackGroups of self.hierarchy.children) {
243
+ if (trackGroups.children.length) {
244
+ findTopLevelCategories(trackGroups.children, paths);
245
+ }
246
+ }
247
+ for (const path of paths) {
248
+ self.setCategoryCollapsed(path, true);
249
+ }
250
+ },
251
+ }))
252
+ .actions(self => ({
253
+ afterCreate() {
254
+ if (!self.initialized) {
255
+ const session = getSession(self);
256
+ if (getConf(session, [
257
+ 'hierarchical',
258
+ 'defaultCollapsed',
259
+ 'topLevelCategories',
260
+ ])) {
261
+ self.collapseTopLevelCategories();
262
+ }
263
+ if (getConf(session, [
264
+ 'hierarchical',
265
+ 'defaultCollapsed',
266
+ 'subCategories',
267
+ ])) {
268
+ self.collapseSubCategories();
269
+ }
270
+ for (const entry of getConf(session, [
271
+ 'hierarchical',
272
+ 'defaultCollapsed',
273
+ 'categoryNames',
274
+ ])) {
275
+ self.collapsed.set(entry, true);
276
+ }
277
+ self.initialized = true;
278
+ }
279
+ },
280
+ }))
281
+ .views(self => ({
282
+ get hasAnySubcategories() {
283
+ return self.allTracks.some(group => group.tracks.some(t => { var _a; return ((_a = readConfObject(t, 'category')) === null || _a === void 0 ? void 0 : _a.length) > 1; }));
251
284
  },
252
285
  }));
253
286
  }
@@ -0,0 +1,12 @@
1
+ import { AnyConfigurationModel } from '@jbrowse/core/configuration';
2
+ import { AbstractSessionModel } from '@jbrowse/core/util';
3
+ export declare function hasAnyOverlap<T>(a1?: T[], a2?: T[]): boolean;
4
+ export declare function hasAllOverlap<T>(a1?: T[], a2?: T[]): boolean;
5
+ export declare function matches(query: string, conf: AnyConfigurationModel, session: AbstractSessionModel): boolean;
6
+ interface Node {
7
+ children: Node[];
8
+ id: string;
9
+ }
10
+ export declare function findSubCategories(obj: Node[], paths: string[]): boolean;
11
+ export declare function findTopLevelCategories(obj: Node[], paths: string[]): void;
12
+ export {};
@@ -0,0 +1,45 @@
1
+ import { readConfObject, } from '@jbrowse/core/configuration';
2
+ import { getTrackName } from '@jbrowse/core/util/tracks';
3
+ export function hasAnyOverlap(a1 = [], a2 = []) {
4
+ // shortcut case is that arrays are single entries, and are equal
5
+ // long case is that we use a set
6
+ if (a1[0] === a2[0]) {
7
+ return true;
8
+ }
9
+ else {
10
+ const s1 = new Set(a1);
11
+ return a2.some(a => s1.has(a));
12
+ }
13
+ }
14
+ export function hasAllOverlap(a1 = [], a2 = []) {
15
+ const s1 = new Set(a1);
16
+ return a2.every(a => s1.has(a));
17
+ }
18
+ export function matches(query, conf, session) {
19
+ const categories = (readConfObject(conf, 'category') || []);
20
+ const queryLower = query.toLowerCase();
21
+ return (getTrackName(conf, session).toLowerCase().includes(queryLower) ||
22
+ !!categories.filter(c => c.toLowerCase().includes(queryLower)).length);
23
+ }
24
+ export function findSubCategories(obj, paths) {
25
+ let hasSubs = false;
26
+ for (const elt of obj) {
27
+ if (elt.children.length) {
28
+ const hasSubCategories = findSubCategories(elt.children, paths);
29
+ if (hasSubCategories) {
30
+ paths.push(elt.id);
31
+ }
32
+ }
33
+ else {
34
+ hasSubs = true;
35
+ }
36
+ }
37
+ return hasSubs;
38
+ }
39
+ export function findTopLevelCategories(obj, paths) {
40
+ for (const elt of obj) {
41
+ if (elt.children.length) {
42
+ paths.push(elt.id);
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { PluginStoreModel } from '../model';
3
+ declare const AddCustomPluginDialog: ({ onClose, model, }: {
4
+ onClose: () => void;
5
+ model: PluginStoreModel;
6
+ }) => React.JSX.Element;
7
+ export default AddCustomPluginDialog;
@@ -1,9 +1,9 @@
1
1
  import React, { useState } from 'react';
2
2
  import { observer } from 'mobx-react';
3
- import { getRoot } from 'mobx-state-tree';
4
3
  import { Dialog } from '@jbrowse/core/ui';
5
4
  import { Button, Collapse, DialogActions, DialogContent, DialogContentText, TextField, } from '@mui/material';
6
5
  import { makeStyles } from 'tss-react/mui';
6
+ import { getSession } from '@jbrowse/core/util';
7
7
  // icons
8
8
  import IconButton from '@mui/material/IconButton';
9
9
  import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
@@ -23,40 +23,32 @@ const useStyles = makeStyles()(theme => ({
23
23
  transform: 'rotate(180deg)',
24
24
  },
25
25
  }));
26
- function CustomPluginForm({ open, onClose, model, }) {
26
+ const AddCustomPluginDialog = observer(function ({ onClose, model, }) {
27
27
  const { classes, cx } = useStyles();
28
28
  const [umdPluginName, setUMDPluginName] = useState('');
29
29
  const [umdPluginUrl, setUMDPluginUrl] = useState('');
30
30
  const [esmPluginUrl, setESMPluginUrl] = useState('');
31
31
  const [cjsPluginUrl, setCJSPluginUrl] = useState('');
32
32
  const [advancedOptionsOpen, setAdvancedOptionsOpen] = useState(false);
33
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
- const { jbrowse } = getRoot(model);
33
+ const { jbrowse } = getSession(model);
35
34
  const ready = Boolean((umdPluginName && umdPluginUrl) || esmPluginUrl || cjsPluginUrl);
36
35
  function handleSubmit() {
37
36
  if (umdPluginName && umdPluginUrl) {
38
37
  jbrowse.addPlugin({ name: umdPluginName, umdUrl: umdPluginUrl });
39
38
  }
40
- if (esmPluginUrl) {
39
+ else if (esmPluginUrl) {
41
40
  jbrowse.addPlugin({ esmUrl: esmPluginUrl });
42
41
  }
43
- if (cjsPluginUrl) {
42
+ else if (cjsPluginUrl) {
44
43
  jbrowse.addPlugin({ cjsUrl: cjsPluginUrl });
45
44
  }
46
45
  }
47
- function handleClose() {
48
- setUMDPluginName('');
49
- setUMDPluginUrl('');
50
- setESMPluginUrl('');
51
- setCJSPluginUrl('');
52
- onClose();
53
- }
54
- return (React.createElement(Dialog, { open: open, onClose: handleClose, title: "Add custom plugin" },
46
+ return (React.createElement(Dialog, { open: true, onClose: onClose, title: "Add custom plugin" },
55
47
  React.createElement("form", { onSubmit: handleSubmit },
56
48
  React.createElement(DialogContent, { className: classes.dialogContent },
57
49
  React.createElement(DialogContentText, null, "Enter the name of the plugin and its URL. The name should match what is defined in the plugin's build."),
58
- React.createElement(TextField, { id: "umd-name-input", name: "umdName", label: "Plugin name", variant: "outlined", value: umdPluginName, onChange: event => setUMDPluginName(event.target.value) }),
59
- React.createElement(TextField, { id: "umd-url-input", name: "umdUrl", label: "Plugin URL", variant: "outlined", value: umdPluginUrl, onChange: event => setUMDPluginUrl(event.target.value) }),
50
+ React.createElement(TextField, { label: "Plugin name", variant: "outlined", value: umdPluginName, onChange: event => setUMDPluginName(event.target.value) }),
51
+ React.createElement(TextField, { label: "Plugin URL", variant: "outlined", value: umdPluginUrl, onChange: event => setUMDPluginUrl(event.target.value) }),
60
52
  React.createElement(DialogContentText, { onClick: () => setAdvancedOptionsOpen(!advancedOptionsOpen) },
61
53
  React.createElement(IconButton, { className: cx(classes.expand, {
62
54
  [classes.expandOpen]: advancedOptionsOpen,
@@ -66,10 +58,10 @@ function CustomPluginForm({ open, onClose, model, }) {
66
58
  React.createElement(Collapse, { in: advancedOptionsOpen },
67
59
  React.createElement("div", { className: classes.dialogContent },
68
60
  React.createElement(DialogContentText, null, "The above fields assume that the plugin is built in UMD format. If your plugin is in another format, or you have additional builds you want to add (such as a CJS build for using NodeJS APIs in desktop), you can enter the URLs for those builds below."),
69
- React.createElement(TextField, { id: "esm-url-input", name: "esmUrl", label: "ESM build URL", variant: "outlined", value: esmPluginUrl, onChange: event => setESMPluginUrl(event.target.value) }),
70
- React.createElement(TextField, { id: "cjs-url-input", name: "cjsUrl", label: "CJS build URL", variant: "outlined", value: cjsPluginUrl, onChange: event => setCJSPluginUrl(event.target.value) })))),
61
+ React.createElement(TextField, { label: "ESM build URL", variant: "outlined", value: esmPluginUrl, onChange: event => setESMPluginUrl(event.target.value) }),
62
+ React.createElement(TextField, { label: "CJS build URL", variant: "outlined", value: cjsPluginUrl, onChange: event => setCJSPluginUrl(event.target.value) })))),
71
63
  React.createElement(DialogActions, null,
72
- React.createElement(Button, { variant: "contained", onClick: handleClose }, "Cancel"),
64
+ React.createElement(Button, { variant: "contained", onClick: onClose }, "Cancel"),
73
65
  React.createElement(Button, { variant: "contained", color: "primary", onClick: handleSubmit, disabled: !ready }, "Submit")))));
74
- }
75
- export default observer(CustomPluginForm);
66
+ });
67
+ export default AddCustomPluginDialog;
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export default function DeletePluginDialog({ onClose, plugin, }: {
3
+ plugin: string;
4
+ onClose: (s?: string) => void;
5
+ }): React.JSX.Element;
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { Button, DialogActions, DialogContent, Typography } from '@mui/material';
3
+ import { Dialog } from '@jbrowse/core/ui';
4
+ export default function DeletePluginDialog({ onClose, plugin, }) {
5
+ return (React.createElement(Dialog, { open: true, onClose: () => onClose(), title: `Remove ${plugin}` },
6
+ React.createElement(DialogContent, null,
7
+ React.createElement(Typography, null,
8
+ "Please confirm that you want to remove ",
9
+ plugin,
10
+ "."),
11
+ React.createElement(Typography, { color: "error" }, "Note: if any resources in this session still use this plugin, it may cause your session to crash")),
12
+ React.createElement(DialogActions, null,
13
+ React.createElement(Button, { variant: "contained", color: "primary", onClick: () => {
14
+ // avoid showing runtime plugin warning
15
+ window.setTimeout(() => {
16
+ onClose(plugin);
17
+ }, 500);
18
+ } }, "Confirm"),
19
+ React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => {
20
+ onClose();
21
+ } }, "Cancel"))));
22
+ }
@@ -1,11 +1,8 @@
1
1
  import React from 'react';
2
- import PluginManager from '@jbrowse/core/PluginManager';
3
2
  import { BasePlugin } from '@jbrowse/core/util/types';
4
3
  import { PluginStoreModel } from '../model';
5
- declare function InstalledPlugin({ plugin, model, pluginManager, }: {
4
+ declare const InstalledPlugin: ({ plugin, model, }: {
6
5
  plugin: BasePlugin;
7
6
  model: PluginStoreModel;
8
- pluginManager: PluginManager;
9
- }): React.JSX.Element;
10
- declare const _default: typeof InstalledPlugin;
11
- export default _default;
7
+ }) => React.JSX.Element;
8
+ export default InstalledPlugin;