@jbrowse/product-core 5.0.0-beta.4 → 5.0.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/RootModel/menuItems.js +3 -3
- package/esm/Session/BaseSession.d.ts +11 -51
- package/esm/Session/BaseSession.js +22 -102
- package/esm/Session/MultipleViews.d.ts +0 -7
- package/esm/Session/Preferences.d.ts +0 -7
- package/esm/Session/Preferences.js +7 -3
- package/esm/Session/SessionTracks.d.ts +0 -7
- package/esm/Session/SessionTracks.js +2 -2
- package/esm/Session/Tracks.d.ts +0 -7
- package/esm/Session/index.d.ts +1 -1
- package/esm/Session/index.js +1 -1
- package/esm/Session/shareableSnapshot.d.ts +6 -60
- package/esm/Session/shareableSnapshot.js +8 -138
- package/esm/index.d.ts +1 -1
- package/esm/index.js +1 -1
- package/esm/observeSession.d.ts +3 -4
- package/esm/observeSession.js +3 -4
- package/esm/sessionMigrations/index.js +3 -3
- package/esm/sessionUrl.d.ts +3 -4
- package/esm/sessionUrl.js +3 -4
- package/esm/ui/AboutDialogContents.js +10 -18
- package/esm/ui/HeaderButtons.d.ts +1 -6
- package/esm/ui/HeaderButtons.js +5 -12
- package/esm/ui/PreferencesDialog.d.ts +1 -2
- package/esm/ui/PreferencesDialog.js +1 -10
- package/esm/ui/preferencesReset.d.ts +2 -4
- package/esm/ui/preferencesReset.js +3 -7
- package/package.json +3 -3
- package/esm/ui/DisplayDefaultsSection.d.ts +0 -23
- package/esm/ui/DisplayDefaultsSection.js +0 -27
- package/esm/ui/displayDefaultChanges.d.ts +0 -31
- package/esm/ui/displayDefaultChanges.js +0 -66
|
@@ -39,9 +39,9 @@ export function exportSessionMenuItem() {
|
|
|
39
39
|
const { saveAs } = await import('@jbrowse/core/util/FileSaver');
|
|
40
40
|
saveAs(new Blob([
|
|
41
41
|
JSON.stringify({
|
|
42
|
-
// an exported file is read by someone
|
|
43
|
-
//
|
|
44
|
-
//
|
|
42
|
+
// an exported file is read by someone whose own preferences
|
|
43
|
+
// differ, so stamp what the live session resolves at read
|
|
44
|
+
// time (same rule as ShareDialog)
|
|
45
45
|
session: getShareableSessionSnapshot(session),
|
|
46
46
|
}, null, 2),
|
|
47
47
|
], { type: 'text/plain;charset=utf-8' }), 'session.json');
|
|
@@ -75,23 +75,15 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
75
75
|
*
|
|
76
76
|
* An `observable.map` (not a plain object reassigned wholesale) so each
|
|
77
77
|
* preference is its own tracked key: writing one (`setScrollZoom`) can't
|
|
78
|
-
* invalidate a reader of another
|
|
79
|
-
*
|
|
80
|
-
* every
|
|
81
|
-
* same reason each promoted per-display-type default is a flat composite
|
|
82
|
-
* key (see `displayTypeDefaultKey`), not a single nested `displayTypeDefaults`
|
|
83
|
-
* object — promoting one default can't wake readers of a different one.
|
|
78
|
+
* invalidate a reader of another. A single spread-replaced object made
|
|
79
|
+
* every setter wake every reader, so toggling scroll-to-zoom re-fetched
|
|
80
|
+
* every track.
|
|
84
81
|
*
|
|
85
|
-
* `deep: false`
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* `
|
|
90
|
-
* `worker.postMessage` threw `DataCloneError` on the next fetch of any
|
|
91
|
-
* track following that default (electron IPC and `structuredClone` in the
|
|
92
|
-
* share bake likewise). The map still notifies per key on `set`, so shallow
|
|
93
|
-
* values lose no reactivity — and nothing can mutate a preference in place,
|
|
94
|
-
* because `setPreferenceOverride` freezes what it stores.
|
|
82
|
+
* `deep: false` keeps an object-valued preference a plain object rather
|
|
83
|
+
* than a MobX Proxy, which V8's structured-clone serializer rejects. The
|
|
84
|
+
* map still notifies per key on `set`, so shallow values lose no
|
|
85
|
+
* reactivity — and nothing can mutate a preference in place, because
|
|
86
|
+
* `setPreferenceOverride` freezes what it stores.
|
|
95
87
|
*/
|
|
96
88
|
preferencesOverrides: import("mobx").ObservableMap<string, unknown>;
|
|
97
89
|
} & {
|
|
@@ -150,35 +142,12 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
150
142
|
* The override map is empty unless the product loads it (web/desktop).
|
|
151
143
|
*/
|
|
152
144
|
getPreference(key: string): unknown;
|
|
153
|
-
/**
|
|
154
|
-
* #method
|
|
155
|
-
* resolved value of a per-display-type slot default the user promoted
|
|
156
|
-
* (see `setDisplayTypeDefault`); undefined when nothing was promoted.
|
|
157
|
-
*/
|
|
158
|
-
getDisplayTypeDefault(displayType: string, slot: string): unknown;
|
|
159
|
-
/**
|
|
160
|
-
* #method
|
|
161
|
-
* every per-display-type default the user has promoted, as
|
|
162
|
-
* `{ displayType, slot, value }` — the inventory the Preferences dialog
|
|
163
|
-
* lists and clears one at a time (`setDisplayTypeDefault(…, undefined)`).
|
|
164
|
-
*
|
|
165
|
-
* Parsed here rather than by the dialog, because the composite-key
|
|
166
|
-
* layout is this file's and nothing outside it should depend on it.
|
|
167
|
-
*/
|
|
168
|
-
getDisplayTypeDefaults(): {
|
|
169
|
-
displayType: string;
|
|
170
|
-
slot: string;
|
|
171
|
-
value: unknown;
|
|
172
|
-
}[];
|
|
173
145
|
/**
|
|
174
146
|
* #method
|
|
175
147
|
* every scalar preference override that currently differs from its
|
|
176
148
|
* config/admin default, as `{ path, from, to }` rows whose path is the
|
|
177
149
|
* override's own key. A scalar pref (animationMode, scrollZoom) whose
|
|
178
150
|
* override equals the default is omitted, since reverting it is a no-op.
|
|
179
|
-
* Promoted display-type defaults share the map but are not here: they
|
|
180
|
-
* are `getDisplayTypeDefaults`, and the Preferences dialog lists them
|
|
181
|
-
* through one builder on both of its surfaces.
|
|
182
151
|
*/
|
|
183
152
|
getPreferenceChanges(): TrackConfigChange[];
|
|
184
153
|
} & {
|
|
@@ -244,10 +213,9 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
244
213
|
setPreferenceOverride(key: string, value: unknown): void;
|
|
245
214
|
/**
|
|
246
215
|
* #action
|
|
247
|
-
* clear every runtime preference override at once
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
* default. Backs the Preferences dialog "Reset to defaults" button.
|
|
216
|
+
* clear every runtime preference override at once, so each falls back to
|
|
217
|
+
* its config/admin default. Backs the Preferences dialog "Reset to
|
|
218
|
+
* defaults" button.
|
|
251
219
|
*/
|
|
252
220
|
clearPreferenceOverrides(): void;
|
|
253
221
|
/**
|
|
@@ -262,14 +230,6 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
262
230
|
* set the global scroll-to-zoom preference (see the `scrollZoom` getter)
|
|
263
231
|
*/
|
|
264
232
|
setScrollZoom(flag: boolean): void;
|
|
265
|
-
/**
|
|
266
|
-
* #action
|
|
267
|
-
* promote (or, with `value` undefined, clear) a per-display-type slot
|
|
268
|
-
* default. Just a preference override under one flat composite key (see
|
|
269
|
-
* `displayTypeDefaultKey`), so it persists and independently tracks like
|
|
270
|
-
* any other pref, and clearing deletes only that key.
|
|
271
|
-
*/
|
|
272
|
-
setDisplayTypeDefault(displayType: string, slot: string, value: unknown): void;
|
|
273
233
|
/**
|
|
274
234
|
* #action
|
|
275
235
|
*/
|
|
@@ -10,35 +10,6 @@ import { applyDeveloperMode } from './developerMode.js';
|
|
|
10
10
|
function isAnimationMode(val) {
|
|
11
11
|
return val === 'system' || val === 'enabled' || val === 'disabled';
|
|
12
12
|
}
|
|
13
|
-
// Promoted per-display-type slot defaults live flat in `preferencesOverrides`
|
|
14
|
-
// under one composite key each (`displayTypeDefault\0<type>\0<slot>`), not under
|
|
15
|
-
// a single nested `displayTypeDefaults` object. Flat keys make each promoted
|
|
16
|
-
// default its own tracked observable-map entry — promoting one can't invalidate
|
|
17
|
-
// a reader of another (every promotable display's `rpcProps` reads one via
|
|
18
|
-
// `getDisplayTypeDefault`) — and collapse the get/set/diff logic to one lookup.
|
|
19
|
-
// The `\0` delimiter can't appear in a display type or slot name.
|
|
20
|
-
// The literal is a **persisted localStorage key prefix**, so treat it as data
|
|
21
|
-
// rather than as an identifier a rename should sweep — a blanket
|
|
22
|
-
// `displayTypeDefault` → `pin` pass did sweep it, and orphans every promoted
|
|
23
|
-
// default already in a browser's storage. Nothing released stores these yet, so
|
|
24
|
-
// the reason it keeps this spelling is naming, not compatibility: the key names
|
|
25
|
-
// *what is stored* (a display-type default, reached through
|
|
26
|
-
// `get/setDisplayTypeDefault`), while `Pin` names the menu control the write
|
|
27
|
-
// is offered from.
|
|
28
|
-
const DISPLAY_TYPE_DEFAULT_PREFIX = 'displayTypeDefault\0';
|
|
29
|
-
// Module-private on purpose: the composite-key spelling is a storage detail of
|
|
30
|
-
// this file's get/set/diff methods, and nothing outside it should be able to
|
|
31
|
-
// depend on the layout.
|
|
32
|
-
function displayTypeDefaultKey(displayType, slot) {
|
|
33
|
-
return `${DISPLAY_TYPE_DEFAULT_PREFIX}${displayType}\0${slot}`;
|
|
34
|
-
}
|
|
35
|
-
function parseDisplayTypeDefaultKey(key) {
|
|
36
|
-
const rest = key.startsWith(DISPLAY_TYPE_DEFAULT_PREFIX)
|
|
37
|
-
? key.slice(DISPLAY_TYPE_DEFAULT_PREFIX.length)
|
|
38
|
-
: '';
|
|
39
|
-
const [displayType, slot] = rest.split('\0');
|
|
40
|
-
return displayType && slot ? { displayType, slot } : undefined;
|
|
41
|
-
}
|
|
42
13
|
/**
|
|
43
14
|
* #stateModel BaseSessionModel
|
|
44
15
|
*
|
|
@@ -113,23 +84,15 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
113
84
|
*
|
|
114
85
|
* An `observable.map` (not a plain object reassigned wholesale) so each
|
|
115
86
|
* preference is its own tracked key: writing one (`setScrollZoom`) can't
|
|
116
|
-
* invalidate a reader of another
|
|
117
|
-
*
|
|
118
|
-
* every
|
|
119
|
-
* same reason each promoted per-display-type default is a flat composite
|
|
120
|
-
* key (see `displayTypeDefaultKey`), not a single nested `displayTypeDefaults`
|
|
121
|
-
* object — promoting one default can't wake readers of a different one.
|
|
87
|
+
* invalidate a reader of another. A single spread-replaced object made
|
|
88
|
+
* every setter wake every reader, so toggling scroll-to-zoom re-fetched
|
|
89
|
+
* every track.
|
|
122
90
|
*
|
|
123
|
-
* `deep: false`
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* `
|
|
128
|
-
* `worker.postMessage` threw `DataCloneError` on the next fetch of any
|
|
129
|
-
* track following that default (electron IPC and `structuredClone` in the
|
|
130
|
-
* share bake likewise). The map still notifies per key on `set`, so shallow
|
|
131
|
-
* values lose no reactivity — and nothing can mutate a preference in place,
|
|
132
|
-
* because `setPreferenceOverride` freezes what it stores.
|
|
91
|
+
* `deep: false` keeps an object-valued preference a plain object rather
|
|
92
|
+
* than a MobX Proxy, which V8's structured-clone serializer rejects. The
|
|
93
|
+
* map still notifies per key on `set`, so shallow values lose no
|
|
94
|
+
* reactivity — and nothing can mutate a preference in place, because
|
|
95
|
+
* `setPreferenceOverride` freezes what it stores.
|
|
133
96
|
*/
|
|
134
97
|
preferencesOverrides: observable.map(undefined, {
|
|
135
98
|
deep: false,
|
|
@@ -219,55 +182,23 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
219
182
|
? this.getPreferenceDefault(key)
|
|
220
183
|
: override;
|
|
221
184
|
},
|
|
222
|
-
/**
|
|
223
|
-
* #method
|
|
224
|
-
* resolved value of a per-display-type slot default the user promoted
|
|
225
|
-
* (see `setDisplayTypeDefault`); undefined when nothing was promoted.
|
|
226
|
-
*/
|
|
227
|
-
getDisplayTypeDefault(displayType, slot) {
|
|
228
|
-
return self.preferencesOverrides.get(displayTypeDefaultKey(displayType, slot));
|
|
229
|
-
},
|
|
230
|
-
/**
|
|
231
|
-
* #method
|
|
232
|
-
* every per-display-type default the user has promoted, as
|
|
233
|
-
* `{ displayType, slot, value }` — the inventory the Preferences dialog
|
|
234
|
-
* lists and clears one at a time (`setDisplayTypeDefault(…, undefined)`).
|
|
235
|
-
*
|
|
236
|
-
* Parsed here rather than by the dialog, because the composite-key
|
|
237
|
-
* layout is this file's and nothing outside it should depend on it.
|
|
238
|
-
*/
|
|
239
|
-
getDisplayTypeDefaults() {
|
|
240
|
-
const found = [];
|
|
241
|
-
for (const [key, value] of self.preferencesOverrides.entries()) {
|
|
242
|
-
const parsed = parseDisplayTypeDefaultKey(key);
|
|
243
|
-
if (parsed) {
|
|
244
|
-
found.push({ ...parsed, value });
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
return found;
|
|
248
|
-
},
|
|
249
185
|
/**
|
|
250
186
|
* #method
|
|
251
187
|
* every scalar preference override that currently differs from its
|
|
252
188
|
* config/admin default, as `{ path, from, to }` rows whose path is the
|
|
253
189
|
* override's own key. A scalar pref (animationMode, scrollZoom) whose
|
|
254
190
|
* override equals the default is omitted, since reverting it is a no-op.
|
|
255
|
-
* Promoted display-type defaults share the map but are not here: they
|
|
256
|
-
* are `getDisplayTypeDefaults`, and the Preferences dialog lists them
|
|
257
|
-
* through one builder on both of its surfaces.
|
|
258
191
|
*/
|
|
259
192
|
getPreferenceChanges() {
|
|
260
193
|
const changes = [];
|
|
261
194
|
for (const [key, value] of self.preferencesOverrides.entries()) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
});
|
|
270
|
-
}
|
|
195
|
+
const dflt = this.getPreferenceDefault(key);
|
|
196
|
+
if (value !== dflt) {
|
|
197
|
+
changes.push({
|
|
198
|
+
path: [key],
|
|
199
|
+
from: dflt,
|
|
200
|
+
to: value,
|
|
201
|
+
});
|
|
271
202
|
}
|
|
272
203
|
}
|
|
273
204
|
return changes;
|
|
@@ -364,19 +295,18 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
364
295
|
self.preferencesOverrides.delete(key);
|
|
365
296
|
}
|
|
366
297
|
else {
|
|
367
|
-
// frozen because `deep: false` hands an object-valued preference
|
|
368
|
-
//
|
|
369
|
-
//
|
|
370
|
-
//
|
|
298
|
+
// frozen because `deep: false` hands an object-valued preference
|
|
299
|
+
// straight back out by reference, so the "nothing mutates a
|
|
300
|
+
// preference in place" this store relies on is enforced rather than
|
|
301
|
+
// assumed
|
|
371
302
|
self.preferencesOverrides.set(key, freezeDeep(value));
|
|
372
303
|
}
|
|
373
304
|
},
|
|
374
305
|
/**
|
|
375
306
|
* #action
|
|
376
|
-
* clear every runtime preference override at once
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
* default. Backs the Preferences dialog "Reset to defaults" button.
|
|
307
|
+
* clear every runtime preference override at once, so each falls back to
|
|
308
|
+
* its config/admin default. Backs the Preferences dialog "Reset to
|
|
309
|
+
* defaults" button.
|
|
380
310
|
*/
|
|
381
311
|
clearPreferenceOverrides() {
|
|
382
312
|
self.preferencesOverrides.clear();
|
|
@@ -397,16 +327,6 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
397
327
|
setScrollZoom(flag) {
|
|
398
328
|
this.setPreferenceOverride('scrollZoom', flag);
|
|
399
329
|
},
|
|
400
|
-
/**
|
|
401
|
-
* #action
|
|
402
|
-
* promote (or, with `value` undefined, clear) a per-display-type slot
|
|
403
|
-
* default. Just a preference override under one flat composite key (see
|
|
404
|
-
* `displayTypeDefaultKey`), so it persists and independently tracks like
|
|
405
|
-
* any other pref, and clearing deletes only that key.
|
|
406
|
-
*/
|
|
407
|
-
setDisplayTypeDefault(displayType, slot, value) {
|
|
408
|
-
this.setPreferenceOverride(displayTypeDefaultKey(displayType, slot), value);
|
|
409
|
-
},
|
|
410
330
|
/**
|
|
411
331
|
* #action
|
|
412
332
|
*/
|
|
@@ -1639,12 +1639,6 @@ export declare function MultipleViewsSessionMixin(pluginManager: PluginManager):
|
|
|
1639
1639
|
} & {
|
|
1640
1640
|
getPreferenceDefault(key: string): unknown;
|
|
1641
1641
|
getPreference(key: string): unknown;
|
|
1642
|
-
getDisplayTypeDefault(displayType: string, slot: string): unknown;
|
|
1643
|
-
getDisplayTypeDefaults(): {
|
|
1644
|
-
displayType: string;
|
|
1645
|
-
slot: string;
|
|
1646
|
-
value: unknown;
|
|
1647
|
-
}[];
|
|
1648
1642
|
getPreferenceChanges(): import("@jbrowse/core/util").TrackConfigChange[];
|
|
1649
1643
|
} & {
|
|
1650
1644
|
readonly animationMode: import("@jbrowse/core/util").AnimationMode;
|
|
@@ -1661,7 +1655,6 @@ export declare function MultipleViewsSessionMixin(pluginManager: PluginManager):
|
|
|
1661
1655
|
clearPreferenceOverrides(): void;
|
|
1662
1656
|
clearPreferenceOverride(key: string): void;
|
|
1663
1657
|
setScrollZoom(flag: boolean): void;
|
|
1664
|
-
setDisplayTypeDefault(displayType: string, slot: string, value: unknown): void;
|
|
1665
1658
|
setName(str: string): void;
|
|
1666
1659
|
setFocusedViewId(viewId: string | undefined): void;
|
|
1667
1660
|
removeActiveDialog(): void;
|
|
@@ -1620,12 +1620,6 @@ export declare function PreferencesSessionMixin(pluginManager: PluginManager): i
|
|
|
1620
1620
|
} & {
|
|
1621
1621
|
getPreferenceDefault(key: string): unknown;
|
|
1622
1622
|
getPreference(key: string): unknown;
|
|
1623
|
-
getDisplayTypeDefault(displayType: string, slot: string): unknown;
|
|
1624
|
-
getDisplayTypeDefaults(): {
|
|
1625
|
-
displayType: string;
|
|
1626
|
-
slot: string;
|
|
1627
|
-
value: unknown;
|
|
1628
|
-
}[];
|
|
1629
1623
|
getPreferenceChanges(): import("@jbrowse/core/util").TrackConfigChange[];
|
|
1630
1624
|
} & {
|
|
1631
1625
|
readonly animationMode: import("@jbrowse/core/util").AnimationMode;
|
|
@@ -1642,7 +1636,6 @@ export declare function PreferencesSessionMixin(pluginManager: PluginManager): i
|
|
|
1642
1636
|
clearPreferenceOverrides(): void;
|
|
1643
1637
|
clearPreferenceOverride(key: string): void;
|
|
1644
1638
|
setScrollZoom(flag: boolean): void;
|
|
1645
|
-
setDisplayTypeDefault(displayType: string, slot: string, value: unknown): void;
|
|
1646
1639
|
setName(str: string): void;
|
|
1647
1640
|
setFocusedViewId(viewId: string | undefined): void;
|
|
1648
1641
|
removeActiveDialog(): void;
|
|
@@ -5,6 +5,11 @@ import { autorun } from 'mobx';
|
|
|
5
5
|
import { BaseSessionModel } from './BaseSession.js';
|
|
6
6
|
import { applyDeveloperMode } from './developerMode.js';
|
|
7
7
|
const PREFS_KEY = 'jbrowsePreferences';
|
|
8
|
+
// v5.0.0-beta.4 shipped session-wide display-type defaults, which persisted here
|
|
9
|
+
// under composite keys of this shape. They resolve to nothing now, and left in
|
|
10
|
+
// place they would show up as unnamed rows in the Preferences reset diff, so a
|
|
11
|
+
// beta user's stored ones are dropped on load.
|
|
12
|
+
const RETIRED_DISPLAY_TYPE_DEFAULT_PREFIX = 'displayTypeDefault\0';
|
|
8
13
|
function loadStoredPreferences() {
|
|
9
14
|
const stored = localStorageGetItem(PREFS_KEY);
|
|
10
15
|
let result = {};
|
|
@@ -12,7 +17,7 @@ function loadStoredPreferences() {
|
|
|
12
17
|
try {
|
|
13
18
|
const parsed = JSON.parse(stored);
|
|
14
19
|
if (typeof parsed === 'object' && parsed !== null) {
|
|
15
|
-
result = parsed;
|
|
20
|
+
result = Object.fromEntries(Object.entries(parsed).filter(([key]) => !key.startsWith(RETIRED_DISPLAY_TYPE_DEFAULT_PREFIX)));
|
|
16
21
|
}
|
|
17
22
|
}
|
|
18
23
|
catch {
|
|
@@ -35,8 +40,7 @@ export function PreferencesSessionMixin(pluginManager) {
|
|
|
35
40
|
.actions(self => ({
|
|
36
41
|
afterAttach() {
|
|
37
42
|
// the restore path bypasses `setPreferenceOverride`, so it freezes here
|
|
38
|
-
// too
|
|
39
|
-
// reference exactly like a freshly set one
|
|
43
|
+
// too
|
|
40
44
|
self.preferencesOverrides.replace(freezeDeep(loadStoredPreferences()));
|
|
41
45
|
// Applied once, here, rather than reactively: the same setting has to
|
|
42
46
|
// hold in the RPC workers (which format tooltip strings from jexl
|
|
@@ -1649,12 +1649,6 @@ export declare function SessionTracksManagerSessionMixin(pluginManager: PluginMa
|
|
|
1649
1649
|
} & {
|
|
1650
1650
|
getPreferenceDefault(key: string): unknown;
|
|
1651
1651
|
getPreference(key: string): unknown;
|
|
1652
|
-
getDisplayTypeDefault(displayType: string, slot: string): unknown;
|
|
1653
|
-
getDisplayTypeDefaults(): {
|
|
1654
|
-
displayType: string;
|
|
1655
|
-
slot: string;
|
|
1656
|
-
value: unknown;
|
|
1657
|
-
}[];
|
|
1658
1652
|
getPreferenceChanges(): import("@jbrowse/core/util").TrackConfigChange[];
|
|
1659
1653
|
} & {
|
|
1660
1654
|
readonly animationMode: import("@jbrowse/core/util").AnimationMode;
|
|
@@ -1671,7 +1665,6 @@ export declare function SessionTracksManagerSessionMixin(pluginManager: PluginMa
|
|
|
1671
1665
|
clearPreferenceOverrides(): void;
|
|
1672
1666
|
clearPreferenceOverride(key: string): void;
|
|
1673
1667
|
setScrollZoom(flag: boolean): void;
|
|
1674
|
-
setDisplayTypeDefault(displayType: string, slot: string, value: unknown): void;
|
|
1675
1668
|
setName(str: string): void;
|
|
1676
1669
|
setFocusedViewId(viewId: string | undefined): void;
|
|
1677
1670
|
removeActiveDialog(): void;
|
|
@@ -486,8 +486,8 @@ export function SessionTracksManagerSessionMixin(pluginManager) {
|
|
|
486
486
|
// base sets diffs to nothing exactly as netting back to the base
|
|
487
487
|
// does — and reverting the working copy then undid the edit ~400ms
|
|
488
488
|
// after the user watched it land. The reachable case is a size
|
|
489
|
-
// row's reset, whose whole job is to unset a slot
|
|
490
|
-
//
|
|
489
|
+
// row's reset, whose whole job is to unset a slot an admin
|
|
490
|
+
// `config.json` declares.
|
|
491
491
|
//
|
|
492
492
|
// The removal still doesn't survive a reload, which is the
|
|
493
493
|
// tombstone-free delta's documented limitation; what it no longer
|
package/esm/Session/Tracks.d.ts
CHANGED
|
@@ -1617,12 +1617,6 @@ export declare function TracksManagerSessionMixin(pluginManager: PluginManager):
|
|
|
1617
1617
|
} & {
|
|
1618
1618
|
getPreferenceDefault(key: string): unknown;
|
|
1619
1619
|
getPreference(key: string): unknown;
|
|
1620
|
-
getDisplayTypeDefault(displayType: string, slot: string): unknown;
|
|
1621
|
-
getDisplayTypeDefaults(): {
|
|
1622
|
-
displayType: string;
|
|
1623
|
-
slot: string;
|
|
1624
|
-
value: unknown;
|
|
1625
|
-
}[];
|
|
1626
1620
|
getPreferenceChanges(): import("@jbrowse/core/util").TrackConfigChange[];
|
|
1627
1621
|
} & {
|
|
1628
1622
|
readonly animationMode: import("@jbrowse/core/util").AnimationMode;
|
|
@@ -1639,7 +1633,6 @@ export declare function TracksManagerSessionMixin(pluginManager: PluginManager):
|
|
|
1639
1633
|
clearPreferenceOverrides(): void;
|
|
1640
1634
|
clearPreferenceOverride(key: string): void;
|
|
1641
1635
|
setScrollZoom(flag: boolean): void;
|
|
1642
|
-
setDisplayTypeDefault(displayType: string, slot: string, value: unknown): void;
|
|
1643
1636
|
setName(str: string): void;
|
|
1644
1637
|
setFocusedViewId(viewId: string | undefined): void;
|
|
1645
1638
|
removeActiveDialog(): void;
|
package/esm/Session/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export { BaseSessionModel, isBaseSession, isSession } from './BaseSession.ts';
|
|
|
15
15
|
export type { BaseSession, BaseSessionType } from './BaseSession.ts';
|
|
16
16
|
export { SessionTracksManagerSessionMixin } from './SessionTracks.ts';
|
|
17
17
|
export type { EditableTrackConfig, PlainTrackConfig, SessionWithSessionTracks, SessionWithSessionTracksType, } from './SessionTracks.ts';
|
|
18
|
-
export {
|
|
18
|
+
export { bakeSessionCascades, getShareableSessionSnapshot, } from './shareableSnapshot.ts';
|
|
19
19
|
export { TrackMenuItemsSessionMixin, aboutTrackMenuItem, copyTrackSnapshot, pluginExtraTrackItems, trackActionItems, trackActionMenuItems, trackListMenuItems, } from './TrackMenu.ts';
|
|
20
20
|
export { TrackMenuSessionMixin } from './TrackMenuSessionMixin.ts';
|
|
21
21
|
export { finalizeSession } from './finalizeSession.ts';
|
package/esm/Session/index.js
CHANGED
|
@@ -7,7 +7,7 @@ export { MultipleViewsSessionMixin, isSessionWithMultipleViews, } from './Multip
|
|
|
7
7
|
export { PreferencesSessionMixin } from './Preferences.js';
|
|
8
8
|
export { BaseSessionModel, isBaseSession, isSession } from './BaseSession.js';
|
|
9
9
|
export { SessionTracksManagerSessionMixin } from './SessionTracks.js';
|
|
10
|
-
export {
|
|
10
|
+
export { bakeSessionCascades, getShareableSessionSnapshot, } from './shareableSnapshot.js';
|
|
11
11
|
export { TrackMenuItemsSessionMixin, aboutTrackMenuItem, copyTrackSnapshot, pluginExtraTrackItems, trackActionItems, trackActionMenuItems, trackListMenuItems, } from './TrackMenu.js';
|
|
12
12
|
export { TrackMenuSessionMixin } from './TrackMenuSessionMixin.js';
|
|
13
13
|
export { finalizeSession } from './finalizeSession.js';
|
|
@@ -12,66 +12,12 @@ import type { AbstractSessionModel } from '@jbrowse/core/util';
|
|
|
12
12
|
export declare function getShareableSessionSnapshot(session: AbstractSessionModel): Record<string, unknown>;
|
|
13
13
|
/**
|
|
14
14
|
* Everything an outgoing snapshot has to resolve because the live session
|
|
15
|
-
* resolves it at read time against state that is staying behind
|
|
15
|
+
* resolves it at read time against state that is staying behind — currently the
|
|
16
|
+
* workspaces intent alone.
|
|
16
17
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* recipient silently resolves their own.
|
|
22
|
-
*
|
|
23
|
-
* They get one entry point rather than a call each because the failure of a
|
|
24
|
-
* boundary that performs half of them is invisible at that boundary — the
|
|
25
|
-
* export succeeds, and what is missing only shows up on someone else's screen.
|
|
26
|
-
* Adding a third cascade should mean editing this function, not auditing four
|
|
27
|
-
* call sites.
|
|
18
|
+
* It keeps its own entry point rather than being inlined into the one caller
|
|
19
|
+
* because the failure of a boundary that performs half of them is invisible at
|
|
20
|
+
* that boundary: the export succeeds, and what is missing only shows up on
|
|
21
|
+
* someone else's screen.
|
|
28
22
|
*/
|
|
29
23
|
export declare function bakeSessionCascades(session: AbstractSessionModel, snapshot: Record<string, unknown>): Record<string, unknown>;
|
|
30
|
-
/**
|
|
31
|
-
* `getComputedStyle` for the promotable-default cascade.
|
|
32
|
-
*
|
|
33
|
-
* A track that "follows" a session-wide promoted display-type default holds no
|
|
34
|
-
* value of its own — its rendered value is resolved at read time from the
|
|
35
|
-
* promoted display-type defaults in `preferencesOverrides`, which are personal,
|
|
36
|
-
* localStorage-backed, and deliberately never serialized into a shared session.
|
|
37
|
-
* So a raw `getSnapshot(session)` records a track as at-default even when the
|
|
38
|
-
* sender is looking at a promoted value, and the recipient (who lacks the sender's
|
|
39
|
-
* preferences) sees something different. This flattens the live cascade into a
|
|
40
|
-
* self-contained snapshot:
|
|
41
|
-
*
|
|
42
|
-
* Every slot an open display *inherits* from a promoted default (i.e.
|
|
43
|
-
* `getDisplayTypeDefaultChanges` — non-customized, differs from base) is baked
|
|
44
|
-
* into that track's config layer: its own config for a user-added or connection
|
|
45
|
-
* track, else a `trackConfigDeltas` entry against the admin base (see
|
|
46
|
-
* `ownTrackConfig`). So the concrete value travels with the document, and
|
|
47
|
-
* because it lands in the track's config the recipient reads it as *customized*
|
|
48
|
-
* — a customized value is the top of the cascade, so their own promoted defaults
|
|
49
|
-
* never get consulted for it.
|
|
50
|
-
*
|
|
51
|
-
* **What this deliberately does not cover**, and the reason there is no flag
|
|
52
|
-
* here: a slot the sender was viewing at its *base* value. Nothing is baked for
|
|
53
|
-
* it (the value equals base, and `stripDefault` drops it from the snapshot
|
|
54
|
-
* regardless), so a recipient who has promoted something else resolves it from
|
|
55
|
-
* their own cascade and sees their value. There is no value that can express "I
|
|
56
|
-
* deliberately saw the default" — at-base and unset are byte-identical once
|
|
57
|
-
* stripped. That case used to be covered by stamping a per-display
|
|
58
|
-
* `ignorePromotedDefaults` on every open display, which cost a second
|
|
59
|
-
* shape-aware walk that had to stay in step with `openPromotableDisplays` by
|
|
60
|
-
* hand, and permanently detached received tracks from the recipient's own pins
|
|
61
|
-
* until they clicked "use this default" on each one. A promoted default is
|
|
62
|
-
* personal and local — the same as the theme a session is viewed in, which this
|
|
63
|
-
* function has never baked either.
|
|
64
|
-
*
|
|
65
|
-
* The live session is untouched; a modified deep copy of `snapshot` is returned.
|
|
66
|
-
* Tracks the sender never opened carry no display state to resolve, so they're
|
|
67
|
-
* left to pick up the recipient's defaults when opened — matching "export the
|
|
68
|
-
* actual state of the (open) tracks".
|
|
69
|
-
*
|
|
70
|
-
* Reach is `openPromotableDisplays` — literally the same walk the cascade's own
|
|
71
|
-
* "apply to open tracks" uses, so the two can't drift. It recurses into a
|
|
72
|
-
* composite view's `views` array (breakpoint-split, the linear-comparative /
|
|
73
|
-
* synteny family), which holds child views rather than tracks of its own —
|
|
74
|
-
* `LGVSyntenyDisplay` is only reachable that way, and before the recursion a
|
|
75
|
-
* shared session containing one rendered differently for the recipient.
|
|
76
|
-
*/
|
|
77
|
-
export declare function bakePromotedDefaultsIntoSnapshot(session: AbstractSessionModel, snapshot: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import { getConf, getDisplayTypeDefaultChanges, } from '@jbrowse/core/configuration';
|
|
2
|
-
import { getContainingTrack, mergeTrackConfig, openPromotableDisplays, } from '@jbrowse/core/util';
|
|
3
1
|
import { getSnapshot } from '@jbrowse/mobx-state-tree';
|
|
4
|
-
import { asArray, isRecord } from '../snapshotUtils.js';
|
|
5
2
|
/**
|
|
6
3
|
* The session snapshot to hand to anyone else — a share link, an exported
|
|
7
4
|
* `session.json`, a desktop→web export. Snapshotting and baking are one call so
|
|
@@ -17,22 +14,16 @@ export function getShareableSessionSnapshot(session) {
|
|
|
17
14
|
}
|
|
18
15
|
/**
|
|
19
16
|
* Everything an outgoing snapshot has to resolve because the live session
|
|
20
|
-
* resolves it at read time against state that is staying behind
|
|
17
|
+
* resolves it at read time against state that is staying behind — currently the
|
|
18
|
+
* workspaces intent alone.
|
|
21
19
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* recipient silently resolves their own.
|
|
27
|
-
*
|
|
28
|
-
* They get one entry point rather than a call each because the failure of a
|
|
29
|
-
* boundary that performs half of them is invisible at that boundary — the
|
|
30
|
-
* export succeeds, and what is missing only shows up on someone else's screen.
|
|
31
|
-
* Adding a third cascade should mean editing this function, not auditing four
|
|
32
|
-
* call sites.
|
|
20
|
+
* It keeps its own entry point rather than being inlined into the one caller
|
|
21
|
+
* because the failure of a boundary that performs half of them is invisible at
|
|
22
|
+
* that boundary: the export succeeds, and what is missing only shows up on
|
|
23
|
+
* someone else's screen.
|
|
33
24
|
*/
|
|
34
25
|
export function bakeSessionCascades(session, snapshot) {
|
|
35
|
-
const snap =
|
|
26
|
+
const snap = structuredClone(snapshot);
|
|
36
27
|
bakeWorkspacesIntent(session, snap);
|
|
37
28
|
return snap;
|
|
38
29
|
}
|
|
@@ -49,8 +40,7 @@ export function bakeSessionCascades(session, snapshot) {
|
|
|
49
40
|
*
|
|
50
41
|
* Only the on case is baked. At `false` there is no arrangement to carry, so
|
|
51
42
|
* stamping it would be a sender with nothing to say overriding a recipient who
|
|
52
|
-
* prefers workspaces
|
|
53
|
-
* the sender was viewing at its base value.
|
|
43
|
+
* prefers workspaces.
|
|
54
44
|
*
|
|
55
45
|
* The paths that build a layout through an explicit user intent already set the
|
|
56
46
|
* property themselves (`setUseWorkspacesPreference`, ViewMenu's move-view-out,
|
|
@@ -74,123 +64,3 @@ function bakeWorkspacesIntent(session, snap) {
|
|
|
74
64
|
snap.useWorkspaces = true;
|
|
75
65
|
}
|
|
76
66
|
}
|
|
77
|
-
/**
|
|
78
|
-
* `getComputedStyle` for the promotable-default cascade.
|
|
79
|
-
*
|
|
80
|
-
* A track that "follows" a session-wide promoted display-type default holds no
|
|
81
|
-
* value of its own — its rendered value is resolved at read time from the
|
|
82
|
-
* promoted display-type defaults in `preferencesOverrides`, which are personal,
|
|
83
|
-
* localStorage-backed, and deliberately never serialized into a shared session.
|
|
84
|
-
* So a raw `getSnapshot(session)` records a track as at-default even when the
|
|
85
|
-
* sender is looking at a promoted value, and the recipient (who lacks the sender's
|
|
86
|
-
* preferences) sees something different. This flattens the live cascade into a
|
|
87
|
-
* self-contained snapshot:
|
|
88
|
-
*
|
|
89
|
-
* Every slot an open display *inherits* from a promoted default (i.e.
|
|
90
|
-
* `getDisplayTypeDefaultChanges` — non-customized, differs from base) is baked
|
|
91
|
-
* into that track's config layer: its own config for a user-added or connection
|
|
92
|
-
* track, else a `trackConfigDeltas` entry against the admin base (see
|
|
93
|
-
* `ownTrackConfig`). So the concrete value travels with the document, and
|
|
94
|
-
* because it lands in the track's config the recipient reads it as *customized*
|
|
95
|
-
* — a customized value is the top of the cascade, so their own promoted defaults
|
|
96
|
-
* never get consulted for it.
|
|
97
|
-
*
|
|
98
|
-
* **What this deliberately does not cover**, and the reason there is no flag
|
|
99
|
-
* here: a slot the sender was viewing at its *base* value. Nothing is baked for
|
|
100
|
-
* it (the value equals base, and `stripDefault` drops it from the snapshot
|
|
101
|
-
* regardless), so a recipient who has promoted something else resolves it from
|
|
102
|
-
* their own cascade and sees their value. There is no value that can express "I
|
|
103
|
-
* deliberately saw the default" — at-base and unset are byte-identical once
|
|
104
|
-
* stripped. That case used to be covered by stamping a per-display
|
|
105
|
-
* `ignorePromotedDefaults` on every open display, which cost a second
|
|
106
|
-
* shape-aware walk that had to stay in step with `openPromotableDisplays` by
|
|
107
|
-
* hand, and permanently detached received tracks from the recipient's own pins
|
|
108
|
-
* until they clicked "use this default" on each one. A promoted default is
|
|
109
|
-
* personal and local — the same as the theme a session is viewed in, which this
|
|
110
|
-
* function has never baked either.
|
|
111
|
-
*
|
|
112
|
-
* The live session is untouched; a modified deep copy of `snapshot` is returned.
|
|
113
|
-
* Tracks the sender never opened carry no display state to resolve, so they're
|
|
114
|
-
* left to pick up the recipient's defaults when opened — matching "export the
|
|
115
|
-
* actual state of the (open) tracks".
|
|
116
|
-
*
|
|
117
|
-
* Reach is `openPromotableDisplays` — literally the same walk the cascade's own
|
|
118
|
-
* "apply to open tracks" uses, so the two can't drift. It recurses into a
|
|
119
|
-
* composite view's `views` array (breakpoint-split, the linear-comparative /
|
|
120
|
-
* synteny family), which holds child views rather than tracks of its own —
|
|
121
|
-
* `LGVSyntenyDisplay` is only reachable that way, and before the recursion a
|
|
122
|
-
* shared session containing one rendered differently for the recipient.
|
|
123
|
-
*/
|
|
124
|
-
export function bakePromotedDefaultsIntoSnapshot(session, snapshot) {
|
|
125
|
-
const snap = structuredClone(snapshot);
|
|
126
|
-
// `openPromotableDisplays` is the one walk that decides reach — shared with
|
|
127
|
-
// the cascade's own "apply to open tracks", so the set this bakes and the set
|
|
128
|
-
// that acts on a promoted default can't drift
|
|
129
|
-
for (const display of openPromotableDisplays(session)) {
|
|
130
|
-
const changes = getDisplayTypeDefaultChanges(display);
|
|
131
|
-
if (changes.length > 0) {
|
|
132
|
-
bakeValues(snap, {
|
|
133
|
-
trackId: getConf(getContainingTrack(display), 'trackId'),
|
|
134
|
-
displayId: getConf(display, 'displayId'),
|
|
135
|
-
displayType: display.type,
|
|
136
|
-
values: Object.fromEntries(changes.map(c => [c.path[0], c.to])),
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return snap;
|
|
141
|
-
}
|
|
142
|
-
// The track's own full config in the snapshot, when it has one: a user-added
|
|
143
|
-
// track's `sessionTracks` entry, or an opened connection track's persisted
|
|
144
|
-
// `connectionTrackConfigs` config. Everything else is an admin-base track,
|
|
145
|
-
// which carries only a delta.
|
|
146
|
-
//
|
|
147
|
-
// The connection case is not optional. `trackConfigDeltas` is merged over
|
|
148
|
-
// `jbrowse.tracks` alone, so a delta written for a connection track resolves
|
|
149
|
-
// nowhere — the recipient would render the base value, which is the exact
|
|
150
|
-
// failure the bake exists to prevent. `updateTrackConfiguration` splits on the
|
|
151
|
-
// same line.
|
|
152
|
-
function ownTrackConfig(snap, trackId) {
|
|
153
|
-
const sessionTrack = asArray(snap.sessionTracks).find(t => isRecord(t) && t.trackId === trackId);
|
|
154
|
-
const connectionEntry = isRecord(snap.connectionTrackConfigs)
|
|
155
|
-
? snap.connectionTrackConfigs[trackId]
|
|
156
|
-
: undefined;
|
|
157
|
-
return isRecord(sessionTrack)
|
|
158
|
-
? sessionTrack
|
|
159
|
-
: isRecord(connectionEntry) && isRecord(connectionEntry.config)
|
|
160
|
-
? connectionEntry.config
|
|
161
|
-
: undefined;
|
|
162
|
-
}
|
|
163
|
-
// Bake one display's inherited values into the config layer: into the matching
|
|
164
|
-
// display of the track's own config when it has one, else merged as a
|
|
165
|
-
// `trackConfigDeltas` entry against the admin base.
|
|
166
|
-
function bakeValues(snap, bake) {
|
|
167
|
-
const partialDisplay = {
|
|
168
|
-
type: bake.displayType,
|
|
169
|
-
displayId: bake.displayId,
|
|
170
|
-
...bake.values,
|
|
171
|
-
};
|
|
172
|
-
const ownConfig = ownTrackConfig(snap, bake.trackId);
|
|
173
|
-
if (ownConfig) {
|
|
174
|
-
const displays = asArray(ownConfig.displays);
|
|
175
|
-
const target = displays.find(d => isRecord(d) && d.displayId === bake.displayId);
|
|
176
|
-
if (isRecord(target)) {
|
|
177
|
-
Object.assign(target, bake.values);
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
ownConfig.displays = [...displays, partialDisplay];
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
const deltas = isRecord(snap.trackConfigDeltas)
|
|
185
|
-
? { ...snap.trackConfigDeltas }
|
|
186
|
-
: {};
|
|
187
|
-
const existing = isRecord(deltas[bake.trackId])
|
|
188
|
-
? deltas[bake.trackId]
|
|
189
|
-
: { trackId: bake.trackId };
|
|
190
|
-
deltas[bake.trackId] = mergeTrackConfig(existing, {
|
|
191
|
-
trackId: bake.trackId,
|
|
192
|
-
displays: [partialDisplay],
|
|
193
|
-
});
|
|
194
|
-
snap.trackConfigDeltas = deltas;
|
|
195
|
-
}
|
|
196
|
-
}
|
package/esm/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { asRoot, asSession } from './siblingCast.ts';
|
|
|
3
3
|
export { scheduleDetachedDestroy } from '@jbrowse/core/util';
|
|
4
4
|
export { BaseRootModelFactory, FormatAboutConfigSchemaFactory, FormatDetailsConfigSchemaFactory, HierarchicalConfigSchemaFactory, InternetAccountsRootModelMixin, PreferencesConfigSchemaFactory, createConfigModel, exportSessionMenuItem, importSessionMenuItem, isRootModel, newSessionMenuItem, openConnectionMenuItem, openTrackMenuItem, pluginStoreMenuItem, preferencesMenuItem, redoMenuItem, undoMenuItem, workspacesMenuItem, } from './RootModel/index.ts';
|
|
5
5
|
export type { BaseRootModel, BaseRootModelType, RootConfigurationSnapshot, RootModelWithInternetAccounts, RootModelWithInternetAccountsType, } from './RootModel/index.ts';
|
|
6
|
-
export { BaseSessionModel, ConnectionManagementSessionMixin, DrawerWidgetSessionMixin, MultipleViewsSessionMixin, PreferencesSessionMixin, ReferenceManagementSessionMixin, SessionTracksManagerSessionMixin, ThemeManagerSessionMixin, TrackMenuItemsSessionMixin, TrackMenuSessionMixin, TracksManagerSessionMixin, aboutTrackMenuItem,
|
|
6
|
+
export { BaseSessionModel, ConnectionManagementSessionMixin, DrawerWidgetSessionMixin, MultipleViewsSessionMixin, PreferencesSessionMixin, ReferenceManagementSessionMixin, SessionTracksManagerSessionMixin, ThemeManagerSessionMixin, TrackMenuItemsSessionMixin, TrackMenuSessionMixin, TracksManagerSessionMixin, aboutTrackMenuItem, bakeSessionCascades, getShareableSessionSnapshot, copyTrackSnapshot, finalizeSession, isBaseSession, isSession, isSessionWithConnections, isSessionWithDrawerWidgets, isSessionWithMultipleViews, isSessionWithReferenceManagement, isSessionWithThemes, isSessionWithTracks, pluginExtraTrackItems, trackActionItems, trackActionMenuItems, trackListMenuItems, } from './Session/index.ts';
|
|
7
7
|
export type { AssertSessionModel, BaseSession, BaseSessionType, ConnectionTrackConfigEntry, EditableTrackConfig, PlainTrackConfig, ReferringNode, SessionWithConnections, SessionWithConnectionsType, SessionWithDrawerWidgets, SessionWithDrawerWidgetsType, SessionWithMultipleViews, SessionWithMultipleViewsType, SessionWithReferenceManagement, SessionWithReferenceManagementType, SessionWithSessionTracks, SessionWithSessionTracksType, SessionWithThemes, SessionWithThemesType, SessionWithTracks, SessionWithTracksType, } from './Session/index.ts';
|
|
8
8
|
export { AboutDialog, Drawer, DrawerControls, DrawerHeader, DrawerWidget, DrawerWidgetSelector, ModalWidget, ModalWidgetAppBar, PreferencesDialog, WidgetBody, WidgetHeading, drawerGridTemplateColumns, } from './ui/index.ts';
|
|
9
9
|
export type { PreferencesDialogSession, PreferencesPanelDescriptor, } from './ui/index.ts';
|
package/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { asRoot, asSession } from './siblingCast.js';
|
|
2
2
|
export { scheduleDetachedDestroy } from '@jbrowse/core/util';
|
|
3
3
|
export { BaseRootModelFactory, FormatAboutConfigSchemaFactory, FormatDetailsConfigSchemaFactory, HierarchicalConfigSchemaFactory, InternetAccountsRootModelMixin, PreferencesConfigSchemaFactory, createConfigModel, exportSessionMenuItem, importSessionMenuItem, isRootModel, newSessionMenuItem, openConnectionMenuItem, openTrackMenuItem, pluginStoreMenuItem, preferencesMenuItem, redoMenuItem, undoMenuItem, workspacesMenuItem, } from './RootModel/index.js';
|
|
4
|
-
export { BaseSessionModel, ConnectionManagementSessionMixin, DrawerWidgetSessionMixin, MultipleViewsSessionMixin, PreferencesSessionMixin, ReferenceManagementSessionMixin, SessionTracksManagerSessionMixin, ThemeManagerSessionMixin, TrackMenuItemsSessionMixin, TrackMenuSessionMixin, TracksManagerSessionMixin, aboutTrackMenuItem,
|
|
4
|
+
export { BaseSessionModel, ConnectionManagementSessionMixin, DrawerWidgetSessionMixin, MultipleViewsSessionMixin, PreferencesSessionMixin, ReferenceManagementSessionMixin, SessionTracksManagerSessionMixin, ThemeManagerSessionMixin, TrackMenuItemsSessionMixin, TrackMenuSessionMixin, TracksManagerSessionMixin, aboutTrackMenuItem, bakeSessionCascades, getShareableSessionSnapshot, copyTrackSnapshot, finalizeSession, isBaseSession, isSession, isSessionWithConnections, isSessionWithDrawerWidgets, isSessionWithMultipleViews, isSessionWithReferenceManagement, isSessionWithThemes, isSessionWithTracks, pluginExtraTrackItems, trackActionItems, trackActionMenuItems, trackListMenuItems, } from './Session/index.js';
|
|
5
5
|
export { AboutDialog, Drawer, DrawerControls, DrawerHeader, DrawerWidget, DrawerWidgetSelector, ModalWidget, ModalWidgetAppBar, PreferencesDialog, WidgetBody, WidgetHeading, drawerGridTemplateColumns, } from './ui/index.js';
|
|
6
6
|
export { initializeWorker } from './rpcWorker.js';
|
|
7
7
|
export { toPluginLoadRecord } from './pluginInput.js';
|
package/esm/observeSession.d.ts
CHANGED
|
@@ -43,10 +43,9 @@ export interface SessionObservers {
|
|
|
43
43
|
* uncompressed twin of `encodeSession`, for hosts that move JSON rather than
|
|
44
44
|
* URLs — a notebook kernel, an R session, a "save this layout" button.
|
|
45
45
|
*
|
|
46
|
-
* Not a plain `getSnapshot`, and for the same reason `encodeSession` isn't:
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* differently for whoever opens it.
|
|
46
|
+
* Not a plain `getSnapshot`, and for the same reason `encodeSession` isn't: a
|
|
47
|
+
* workspace arrangement turned on by the sender's preference is not in the
|
|
48
|
+
* snapshot, so a raw one replays as a classic stack for whoever opens it.
|
|
50
49
|
*/
|
|
51
50
|
export declare function getSessionSnapshot(session: ObservedSession): SessionSnapshot;
|
|
52
51
|
/**
|
package/esm/observeSession.js
CHANGED
|
@@ -7,10 +7,9 @@ import { getShareableSessionSnapshot } from './Session/shareableSnapshot.js';
|
|
|
7
7
|
* uncompressed twin of `encodeSession`, for hosts that move JSON rather than
|
|
8
8
|
* URLs — a notebook kernel, an R session, a "save this layout" button.
|
|
9
9
|
*
|
|
10
|
-
* Not a plain `getSnapshot`, and for the same reason `encodeSession` isn't:
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* differently for whoever opens it.
|
|
10
|
+
* Not a plain `getSnapshot`, and for the same reason `encodeSession` isn't: a
|
|
11
|
+
* workspace arrangement turned on by the sender's preference is not in the
|
|
12
|
+
* snapshot, so a raw one replays as a classic stack for whoever opens it.
|
|
14
13
|
*/
|
|
15
14
|
export function getSessionSnapshot(session) {
|
|
16
15
|
// `name` is restated rather than the whole thing cast: the bake returns an
|
|
@@ -136,9 +136,9 @@ function isObject(v) {
|
|
|
136
136
|
// The standalone `methylation` colorBy scheme was removed; it is now the
|
|
137
137
|
// `modifications` scheme with `fillUnmarked` set. It is NOT rewritten here: the
|
|
138
138
|
// alignments model normalizes it at read time (`normalizeColorBy`, applied in
|
|
139
|
-
// its `colorBy` getter), which covers every persistence path — instance slot
|
|
140
|
-
//
|
|
141
|
-
//
|
|
139
|
+
// its `colorBy` getter), which covers every persistence path — instance slot and
|
|
140
|
+
// config-file display default alike — so session migration deliberately leaves a
|
|
141
|
+
// `methylation` colorBy untouched.
|
|
142
142
|
function migrateDisplayType(display, trackConfigId, collected) {
|
|
143
143
|
const entry = displayTypeMap[display.type];
|
|
144
144
|
if (!entry) {
|
package/esm/sessionUrl.d.ts
CHANGED
|
@@ -12,10 +12,9 @@ export interface SessionSnapshot {
|
|
|
12
12
|
* hash fragment. Deflated then base64url-encoded, so it survives a URL intact
|
|
13
13
|
* and stays far smaller than raw JSON.
|
|
14
14
|
*
|
|
15
|
-
* Not a plain `getSnapshot`:
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* `getShareableSessionSnapshot` flattens that cascade into the snapshot first.
|
|
15
|
+
* Not a plain `getSnapshot`: a workspace arrangement turned on by the sender's
|
|
16
|
+
* preference is not in the snapshot, so a raw one renders as a classic stack
|
|
17
|
+
* for whoever opens the link. `getShareableSessionSnapshot` stamps it first.
|
|
19
18
|
*
|
|
20
19
|
* The session travels but the config does not — the receiving app supplies its
|
|
21
20
|
* own assembly/tracks. Put the result somewhere the server never sees (the hash
|
package/esm/sessionUrl.js
CHANGED
|
@@ -5,10 +5,9 @@ import { getShareableSessionSnapshot } from './Session/index.js';
|
|
|
5
5
|
* hash fragment. Deflated then base64url-encoded, so it survives a URL intact
|
|
6
6
|
* and stays far smaller than raw JSON.
|
|
7
7
|
*
|
|
8
|
-
* Not a plain `getSnapshot`:
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* `getShareableSessionSnapshot` flattens that cascade into the snapshot first.
|
|
8
|
+
* Not a plain `getSnapshot`: a workspace arrangement turned on by the sender's
|
|
9
|
+
* preference is not in the snapshot, so a raw one renders as a classic stack
|
|
10
|
+
* for whoever opens the link. `getShareableSessionSnapshot` stamps it first.
|
|
12
11
|
*
|
|
13
12
|
* The session travels but the config does not — the receiving app supplies its
|
|
14
13
|
* own assembly/tracks. Put the result somewhere the server never sees (the hash
|
|
@@ -2,11 +2,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import Attributes from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail/Attributes';
|
|
4
4
|
import BaseCard from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail/BaseCard';
|
|
5
|
-
import {
|
|
5
|
+
import { hydrateTrackConfig } from '@jbrowse/core/configuration';
|
|
6
6
|
import PluggableComponents from '@jbrowse/core/ui/PluggableComponents';
|
|
7
7
|
import { getEnv } from '@jbrowse/core/util';
|
|
8
8
|
import { makeStyles } from '@jbrowse/core/util/tss-react';
|
|
9
|
-
import { isStateTreeNode } from '@jbrowse/mobx-state-tree';
|
|
9
|
+
import { getSnapshot, isStateTreeNode } from '@jbrowse/mobx-state-tree';
|
|
10
10
|
import { observer } from 'mobx-react';
|
|
11
11
|
import AssemblyInfoPanel from './AssemblyInfoPanel.js';
|
|
12
12
|
import DescriptionPanel from './DescriptionPanel.js';
|
|
@@ -24,33 +24,25 @@ const AboutDialogContents = observer(function AboutDialogContents({ config, sess
|
|
|
24
24
|
const { classes } = useStyles();
|
|
25
25
|
const [showRefNames, setShowRefNames] = useState(false);
|
|
26
26
|
const { pluginManager } = getEnv(session);
|
|
27
|
-
// "Copy config" output leaves the cascade for good (a user pastes it into a
|
|
28
|
-
// config.json), so promotable slots are resolved rather than left stripped —
|
|
29
|
-
// otherwise the copied config renders differently from the track it came from.
|
|
30
|
-
// `fromDisplayTypeDefaults` names what that folded in, so materializing a
|
|
31
|
-
// session-wide preference into a track config isn't silent.
|
|
32
|
-
//
|
|
33
27
|
// The two menus that open this dialog hand over different things: the in-view
|
|
34
28
|
// track label passes `track.configuration`, a live node, while the
|
|
35
29
|
// hierarchical selector passes a `session.tracks` entry, which is a
|
|
36
|
-
// `types.frozen` plain object until something references the track.
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
// undefined for a config no plugin can build, and that falls back to copying
|
|
41
|
-
// it as authored.
|
|
30
|
+
// `types.frozen` plain object until something references the track. Hydrating
|
|
31
|
+
// converges them, so "Copy config" gives the same JSON whichever menu you came
|
|
32
|
+
// from; it returns undefined for a config no plugin can build, and that falls
|
|
33
|
+
// back to copying it as authored.
|
|
42
34
|
const live = isStateTreeNode(config)
|
|
43
35
|
? config
|
|
44
36
|
: hydrateTrackConfig(pluginManager, config);
|
|
45
|
-
const
|
|
46
|
-
?
|
|
47
|
-
:
|
|
37
|
+
const conf = live
|
|
38
|
+
? getSnapshot(live)
|
|
39
|
+
: config;
|
|
48
40
|
const { config: shown, hideUris } = getAboutDialogConfig({
|
|
49
41
|
config,
|
|
50
42
|
session,
|
|
51
43
|
pluginManager,
|
|
52
44
|
});
|
|
53
|
-
return (_jsxs("div", { className: classes.content, children: [_jsxs(BaseCard, { title: "Configuration", children: [_jsx(HeaderButtons, { conf: conf, hideUris: hideUris,
|
|
45
|
+
return (_jsxs("div", { className: classes.content, children: [_jsxs(BaseCard, { title: "Configuration", children: [_jsx(HeaderButtons, { conf: conf, hideUris: hideUris, setShowRefNames: setShowRefNames }), _jsx(Attributes, { attributes: shown, omit: [...hideFields, 'metadata'], hideUris: hideUris })] }), shown.metadata ? (_jsx(BaseCard, { title: "Metadata", children: _jsx(Attributes, { attributes: shown.metadata, hideUris: hideUris }) })) : null, _jsx(DescriptionPanel, { config: config, session: session }), _jsx(AssemblyInfoPanel, { config: config, session: session, hideUris: hideUris }), _jsx(PluggableComponents, { pluginManager: pluginManager,
|
|
54
46
|
/** #extensionPoint Core-extraAboutPanel | sync | Add extra panels to a track's About dialog */
|
|
55
47
|
name: "Core-extraAboutPanel", props: { session, config } }), hideUris ? null : _jsx(FileInfoPanel, { config: config, session: session }), showRefNames ? (_jsx(RefNameInfoDialog, { session: session, config: config, onClose: () => {
|
|
56
48
|
setShowRefNames(false);
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
interface HeaderButtonsProps {
|
|
2
2
|
conf: Record<string, unknown>;
|
|
3
3
|
hideUris?: boolean;
|
|
4
|
-
/**
|
|
5
|
-
* `<displayType>.<slot>` for each value the copied config inherited from a
|
|
6
|
-
* session-wide display-type default rather than from the config itself
|
|
7
|
-
*/
|
|
8
|
-
fromDisplayTypeDefaults?: string[];
|
|
9
4
|
setShowRefNames: (show: boolean) => void;
|
|
10
5
|
}
|
|
11
|
-
declare function HeaderButtons({ conf, hideUris,
|
|
6
|
+
declare function HeaderButtons({ conf, hideUris, setShowRefNames, }: HeaderButtonsProps): import("react").JSX.Element;
|
|
12
7
|
export default HeaderButtons;
|
package/esm/ui/HeaderButtons.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { CopyToClipboardButton } from '@jbrowse/core/ui';
|
|
3
|
-
import { pluralize } from '@jbrowse/core/util';
|
|
4
3
|
import { stripBaseUris } from '@jbrowse/core/util/addRelativeUris';
|
|
5
4
|
import { makeStyles } from '@jbrowse/core/util/tss-react';
|
|
6
|
-
import { Button
|
|
5
|
+
import { Button } from '@mui/material';
|
|
7
6
|
const useStyles = makeStyles()(theme => ({
|
|
8
7
|
button: {
|
|
9
8
|
float: 'right',
|
|
@@ -15,17 +14,11 @@ const useStyles = makeStyles()(theme => ({
|
|
|
15
14
|
gap: theme.spacing(1),
|
|
16
15
|
justifyContent: 'flex-end',
|
|
17
16
|
},
|
|
18
|
-
note: {
|
|
19
|
-
clear: 'both',
|
|
20
|
-
display: 'block',
|
|
21
|
-
textAlign: 'right',
|
|
22
|
-
},
|
|
23
17
|
}));
|
|
24
|
-
function HeaderButtons({ conf, hideUris,
|
|
18
|
+
function HeaderButtons({ conf, hideUris, setShowRefNames, }) {
|
|
25
19
|
const { classes } = useStyles();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}, children: "Show ref names" }), hideUris ? null : (_jsx(CopyToClipboardButton, { variant: "contained", value: () => JSON.stringify(stripBaseUris(structuredClone(conf)), null, 2), children: "Copy config" }))] }), hideUris || !n ? null : (_jsx(Tooltip, { title: fromDisplayTypeDefaults.join(', '), children: _jsxs(Typography, { variant: "caption", color: "textSecondary", className: classes.note, children: ["includes ", n, " ", pluralize(n, 'setting'), " from your session-wide defaults"] }) }))] }));
|
|
20
|
+
return (_jsx("span", { className: classes.button, children: _jsxs("span", { className: classes.buttons, children: [_jsx(Button, { variant: "contained", color: "secondary", onClick: () => {
|
|
21
|
+
setShowRefNames(true);
|
|
22
|
+
}, children: "Show ref names" }), hideUris ? null : (_jsx(CopyToClipboardButton, { variant: "contained", value: () => JSON.stringify(stripBaseUris(structuredClone(conf)), null, 2), children: "Copy config" }))] }) }));
|
|
30
23
|
}
|
|
31
24
|
export default HeaderButtons;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type { DisplayDefaultsSession } from './DisplayDefaultsSection.tsx';
|
|
2
1
|
import type { GeneralPreferencesSession } from './GeneralPreferencesTab.tsx';
|
|
3
2
|
import type { ViewPreferencesSession } from './ViewPreferencesTab.tsx';
|
|
4
3
|
import type { ResettablePreferencesSession } from './preferencesReset.ts';
|
|
5
4
|
import type PluginManager from '@jbrowse/core/PluginManager';
|
|
6
5
|
import type React from 'react';
|
|
7
|
-
export interface PreferencesDialogSession extends GeneralPreferencesSession, ViewPreferencesSession,
|
|
6
|
+
export interface PreferencesDialogSession extends GeneralPreferencesSession, ViewPreferencesSession, ResettablePreferencesSession {
|
|
8
7
|
}
|
|
9
8
|
/**
|
|
10
9
|
* Descriptor returned from the `Core-preferencesDialogPanels` extension point.
|
|
@@ -4,7 +4,6 @@ import { Dialog } from '@jbrowse/core/ui';
|
|
|
4
4
|
import { makeStyles } from '@jbrowse/core/util/tss-react';
|
|
5
5
|
import { Button, DialogActions, DialogContent, Tab, Tabs } from '@mui/material';
|
|
6
6
|
import { observer } from 'mobx-react';
|
|
7
|
-
import DisplayDefaultsSection from './DisplayDefaultsSection.js';
|
|
8
7
|
import GeneralPreferencesTab from './GeneralPreferencesTab.js';
|
|
9
8
|
import PreferencesResetDialog from './PreferencesResetDialog.js';
|
|
10
9
|
import ViewPreferencesTab from './ViewPreferencesTab.js';
|
|
@@ -22,7 +21,6 @@ const PreferencesDialog = observer(function PreferencesDialog({ handleClose, ses
|
|
|
22
21
|
const pluginPanels = pluginManager.evaluateExtensionPoint(
|
|
23
22
|
/** #extensionPoint Core-preferencesDialogPanels | sync | Add tabs to the preferences dialog */
|
|
24
23
|
'Core-preferencesDialogPanels', [], { session });
|
|
25
|
-
const displayDefaultCount = session.getDisplayTypeDefaults().length;
|
|
26
24
|
const tabs = [
|
|
27
25
|
{
|
|
28
26
|
value: 'general',
|
|
@@ -34,13 +32,6 @@ const PreferencesDialog = observer(function PreferencesDialog({ handleClose, ses
|
|
|
34
32
|
label: 'Views',
|
|
35
33
|
content: _jsx(ViewPreferencesTab, { session: session }),
|
|
36
34
|
},
|
|
37
|
-
{
|
|
38
|
-
value: 'displayDefaults',
|
|
39
|
-
label: displayDefaultCount
|
|
40
|
-
? `Display defaults (${displayDefaultCount})`
|
|
41
|
-
: 'Display defaults',
|
|
42
|
-
content: (_jsx(DisplayDefaultsSection, { session: session, pluginManager: pluginManager })),
|
|
43
|
-
},
|
|
44
35
|
...pluginPanels.map(({ name, Component }) => ({
|
|
45
36
|
value: `plugin:${name}`,
|
|
46
37
|
label: name,
|
|
@@ -53,7 +44,7 @@ const PreferencesDialog = observer(function PreferencesDialog({ handleClose, ses
|
|
|
53
44
|
setResetDialogOpen(true);
|
|
54
45
|
}, children: "Reset to defaults\u2026" }), _jsx(Button, { variant: "contained", onClick: () => {
|
|
55
46
|
handleClose();
|
|
56
|
-
}, children: "Close" })] }), resetDialogOpen ? (_jsx(PreferencesResetDialog, { changes: collectPreferenceChanges(session
|
|
47
|
+
}, children: "Close" })] }), resetDialogOpen ? (_jsx(PreferencesResetDialog, { changes: collectPreferenceChanges(session), onReset: () => {
|
|
57
48
|
resetAllPreferences(session);
|
|
58
49
|
}, onResetRow: change => {
|
|
59
50
|
resetPreferenceChange(session, change);
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import type { DisplayDefaultsSession } from './displayDefaultChanges.ts';
|
|
2
|
-
import type PluginManager from '@jbrowse/core/PluginManager';
|
|
3
1
|
import type { TrackConfigChange } from '@jbrowse/core/util';
|
|
4
|
-
export interface ResettablePreferencesSession
|
|
2
|
+
export interface ResettablePreferencesSession {
|
|
5
3
|
themeName?: string;
|
|
6
4
|
setThemeName: (arg: string) => void;
|
|
7
5
|
stickyViewHeaders: boolean;
|
|
@@ -13,6 +11,6 @@ export interface ResettablePreferencesSession extends DisplayDefaultsSession {
|
|
|
13
11
|
clearPreferenceOverride: (key: string) => void;
|
|
14
12
|
getPreferenceChanges: () => TrackConfigChange[];
|
|
15
13
|
}
|
|
16
|
-
export declare function collectPreferenceChanges(session: ResettablePreferencesSession
|
|
14
|
+
export declare function collectPreferenceChanges(session: ResettablePreferencesSession): TrackConfigChange[];
|
|
17
15
|
export declare function resetAllPreferences(session: ResettablePreferencesSession): void;
|
|
18
16
|
export declare function resetPreferenceChange(session: ResettablePreferencesSession, change: TrackConfigChange): void;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { displayDefaultChanges, resetDisplayDefault, } from './displayDefaultChanges.js';
|
|
2
1
|
const NON_MAP_PREFERENCES = [
|
|
3
2
|
{
|
|
4
3
|
head: 'theme',
|
|
@@ -34,15 +33,12 @@ const NON_MAP_PREFERENCES = [
|
|
|
34
33
|
];
|
|
35
34
|
const NON_MAP_HEADS = new Set(NON_MAP_PREFERENCES.map(p => p.head));
|
|
36
35
|
// Everything "Reset to defaults" reverts, as rows: the scalar overrides in the
|
|
37
|
-
// preference map, the
|
|
38
|
-
|
|
39
|
-
// and the preferences held outside the map.
|
|
40
|
-
export function collectPreferenceChanges(session, pluginManager) {
|
|
36
|
+
// preference map, and the preferences held outside it.
|
|
37
|
+
export function collectPreferenceChanges(session) {
|
|
41
38
|
return [
|
|
42
39
|
...session
|
|
43
40
|
.getPreferenceChanges()
|
|
44
41
|
.filter(c => !NON_MAP_HEADS.has(c.path[0])),
|
|
45
|
-
...displayDefaultChanges(session, pluginManager),
|
|
46
42
|
...NON_MAP_PREFERENCES.map(p => p.change(session)).filter(c => c !== undefined),
|
|
47
43
|
];
|
|
48
44
|
}
|
|
@@ -58,7 +54,7 @@ export function resetPreferenceChange(session, change) {
|
|
|
58
54
|
if (pref) {
|
|
59
55
|
pref.reset(session);
|
|
60
56
|
}
|
|
61
|
-
else if (
|
|
57
|
+
else if (head) {
|
|
62
58
|
session.clearPreferenceOverride(head);
|
|
63
59
|
}
|
|
64
60
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/product-core",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "JBrowse 2 code shared between products but not used by plugins",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"@mui/material": "^9.4.0",
|
|
31
31
|
"mobx": "^7.0.3",
|
|
32
32
|
"mobx-react": "^10.0.2",
|
|
33
|
-
"@jbrowse/
|
|
34
|
-
"@jbrowse/core": "^5.0.0-beta.
|
|
33
|
+
"@jbrowse/core": "^5.0.0-beta.7",
|
|
34
|
+
"@jbrowse/render-core": "^5.0.0-beta.7"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"react": ">=19.0.0",
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { DisplayDefaultsSession } from './displayDefaultChanges.ts';
|
|
2
|
-
import type PluginManager from '@jbrowse/core/PluginManager';
|
|
3
|
-
export type { DisplayDefaultsSession } from './displayDefaultChanges.ts';
|
|
4
|
-
/**
|
|
5
|
-
* The inventory of session-wide display-type defaults: every value the user has
|
|
6
|
-
* pinned from a track menu, what it overrides, and a button to clear one.
|
|
7
|
-
*
|
|
8
|
-
* The pin is easy to set and, until this, hard to find again. A pinned default
|
|
9
|
-
* shows on the track-selector badge of any **open** track it moves — but one
|
|
10
|
-
* affecting nothing currently open, and one that no longer resolves at all (a
|
|
11
|
-
* stale value the cascade refuses, or a display type whose plugin is gone)
|
|
12
|
-
* appear nowhere. The only place that listed them was the "Reset preferences to
|
|
13
|
-
* defaults" confirmation, which is a destructive dialog to have to open in
|
|
14
|
-
* order to read something.
|
|
15
|
-
*
|
|
16
|
-
* The empty state is deliberate rather than rendering nothing: it is the one
|
|
17
|
-
* place the app says the capability exists to someone who has never used it.
|
|
18
|
-
*/
|
|
19
|
-
declare const DisplayDefaultsSection: ({ session, pluginManager, }: {
|
|
20
|
-
session: DisplayDefaultsSession;
|
|
21
|
-
pluginManager: PluginManager;
|
|
22
|
-
}) => import("react").JSX.Element;
|
|
23
|
-
export default DisplayDefaultsSection;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { SettingsChangesTable } from '@jbrowse/core/ui';
|
|
3
|
-
import { Typography } from '@mui/material';
|
|
4
|
-
import { observer } from 'mobx-react';
|
|
5
|
-
import { displayDefaultChanges, resetDisplayDefault, } from './displayDefaultChanges.js';
|
|
6
|
-
/**
|
|
7
|
-
* The inventory of session-wide display-type defaults: every value the user has
|
|
8
|
-
* pinned from a track menu, what it overrides, and a button to clear one.
|
|
9
|
-
*
|
|
10
|
-
* The pin is easy to set and, until this, hard to find again. A pinned default
|
|
11
|
-
* shows on the track-selector badge of any **open** track it moves — but one
|
|
12
|
-
* affecting nothing currently open, and one that no longer resolves at all (a
|
|
13
|
-
* stale value the cascade refuses, or a display type whose plugin is gone)
|
|
14
|
-
* appear nowhere. The only place that listed them was the "Reset preferences to
|
|
15
|
-
* defaults" confirmation, which is a destructive dialog to have to open in
|
|
16
|
-
* order to read something.
|
|
17
|
-
*
|
|
18
|
-
* The empty state is deliberate rather than rendering nothing: it is the one
|
|
19
|
-
* place the app says the capability exists to someone who has never used it.
|
|
20
|
-
*/
|
|
21
|
-
const DisplayDefaultsSection = observer(function DisplayDefaultsSection({ session, pluginManager, }) {
|
|
22
|
-
const changes = displayDefaultChanges(session, pluginManager);
|
|
23
|
-
return changes.length ? (_jsxs(_Fragment, { children: [_jsx(Typography, { children: "These apply to every track of a display type that hasn't set its own value. Clear one to put those tracks back on the setting's default." }), _jsx(SettingsChangesTable, { changes: changes, onResetRow: change => {
|
|
24
|
-
resetDisplayDefault(session, change);
|
|
25
|
-
} })] })) : (_jsx(Typography, { children: "None set. The pin beside a setting in a track menu applies that value to every open track of the same display type, and then offers to keep it as the default for the ones you open later." }));
|
|
26
|
-
});
|
|
27
|
-
export default DisplayDefaultsSection;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type PluginManager from '@jbrowse/core/PluginManager';
|
|
2
|
-
import type { TrackConfigChange } from '@jbrowse/core/util';
|
|
3
|
-
export interface DisplayDefaultsSession {
|
|
4
|
-
getDisplayTypeDefaults: () => {
|
|
5
|
-
displayType: string;
|
|
6
|
-
slot: string;
|
|
7
|
-
value: unknown;
|
|
8
|
-
}[];
|
|
9
|
-
setDisplayTypeDefault: (displayType: string, slot: string, value: unknown) => void;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Every promoted display-type default as a settings row: what it overrides
|
|
13
|
-
* (the slot's `promotedBase`), the value, and a label naming the display type
|
|
14
|
-
* the way the user knows it. One builder for the two surfaces that list them,
|
|
15
|
-
* the Display defaults section and the "Reset to defaults" confirmation, which
|
|
16
|
-
* used to render the same default two ways.
|
|
17
|
-
*
|
|
18
|
-
* **The slot keeps its schema name**, while the display type gets its authored
|
|
19
|
-
* one. A slot has no menu label to borrow — which row a setting is offered on is
|
|
20
|
-
* a menu fact and declaring the slot promotable is a schema fact, and nothing
|
|
21
|
-
* joins them (that split is why `promotableSlotsWithoutPin` has to walk a built
|
|
22
|
-
* menu at all). A raw slot name is also what the config editor labels its fields
|
|
23
|
-
* with, so the two surfaces agree.
|
|
24
|
-
*/
|
|
25
|
-
export declare function displayDefaultChanges(session: DisplayDefaultsSession, pluginManager: PluginManager): TrackConfigChange[];
|
|
26
|
-
/**
|
|
27
|
-
* Clear the promoted default a row built by {@link displayDefaultChanges}
|
|
28
|
-
* stands for. Returns false for any other row, so a table mixing both kinds
|
|
29
|
-
* can hand every reset here first.
|
|
30
|
-
*/
|
|
31
|
-
export declare function resetDisplayDefault(session: DisplayDefaultsSession, change: TrackConfigChange): boolean;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { getConfigurationSchemaDefinition, isSlotDefinitionEntry, } from '@jbrowse/core/configuration';
|
|
2
|
-
// Head of the path a promoted default's row carries, so `resetDisplayDefault`
|
|
3
|
-
// can tell it from a scalar preference row in the same table. Module-private:
|
|
4
|
-
// the one producer and the one consumer of the shape are both here, which is
|
|
5
|
-
// what lets the session know nothing about how the Preferences dialog
|
|
6
|
-
// addresses a row.
|
|
7
|
-
const DISPLAY_DEFAULT_PATH_HEAD = 'displayTypeDefaults';
|
|
8
|
-
// The registered display types, by name.
|
|
9
|
-
//
|
|
10
|
-
// **Built rather than reached through `getDisplayType`, which THROWS** on a name
|
|
11
|
-
// no plugin registers — an optional chain over it guards nothing. A default left
|
|
12
|
-
// behind by a plugin that has since been uninstalled is exactly a row this
|
|
13
|
-
// section has to render, so reaching for that getter would crash the whole
|
|
14
|
-
// Preferences dialog for the one user whose pins most need clearing.
|
|
15
|
-
function displayTypesByName(pluginManager) {
|
|
16
|
-
return new Map(pluginManager.getDisplayElements().map(d => [d.name, d]));
|
|
17
|
-
}
|
|
18
|
-
// What a track sitting at the bottom of the cascade shows for this slot — the
|
|
19
|
-
// value clearing the pin would restore. Read off the display type's schema
|
|
20
|
-
// rather than off the session, which holds only what was promoted. Undefined
|
|
21
|
-
// for a display type that is gone, whose row then reads "(default)" like any
|
|
22
|
-
// other unknown.
|
|
23
|
-
function promotedBaseOf(configSchema, slot) {
|
|
24
|
-
const def = configSchema
|
|
25
|
-
? getConfigurationSchemaDefinition(configSchema)?.[slot]
|
|
26
|
-
: undefined;
|
|
27
|
-
return isSlotDefinitionEntry(def) ? def.promotedBase : undefined;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Every promoted display-type default as a settings row: what it overrides
|
|
31
|
-
* (the slot's `promotedBase`), the value, and a label naming the display type
|
|
32
|
-
* the way the user knows it. One builder for the two surfaces that list them,
|
|
33
|
-
* the Display defaults section and the "Reset to defaults" confirmation, which
|
|
34
|
-
* used to render the same default two ways.
|
|
35
|
-
*
|
|
36
|
-
* **The slot keeps its schema name**, while the display type gets its authored
|
|
37
|
-
* one. A slot has no menu label to borrow — which row a setting is offered on is
|
|
38
|
-
* a menu fact and declaring the slot promotable is a schema fact, and nothing
|
|
39
|
-
* joins them (that split is why `promotableSlotsWithoutPin` has to walk a built
|
|
40
|
-
* menu at all). A raw slot name is also what the config editor labels its fields
|
|
41
|
-
* with, so the two surfaces agree.
|
|
42
|
-
*/
|
|
43
|
-
export function displayDefaultChanges(session, pluginManager) {
|
|
44
|
-
const byName = displayTypesByName(pluginManager);
|
|
45
|
-
return session
|
|
46
|
-
.getDisplayTypeDefaults()
|
|
47
|
-
.map(({ displayType, slot, value }) => ({
|
|
48
|
-
path: [DISPLAY_DEFAULT_PATH_HEAD, displayType, slot],
|
|
49
|
-
label: `${byName.get(displayType)?.displayName ?? displayType} › ${slot}`,
|
|
50
|
-
from: promotedBaseOf(byName.get(displayType)?.configSchema, slot),
|
|
51
|
-
to: value,
|
|
52
|
-
}));
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Clear the promoted default a row built by {@link displayDefaultChanges}
|
|
56
|
-
* stands for. Returns false for any other row, so a table mixing both kinds
|
|
57
|
-
* can hand every reset here first.
|
|
58
|
-
*/
|
|
59
|
-
export function resetDisplayDefault(session, change) {
|
|
60
|
-
const [head, displayType, slot] = change.path;
|
|
61
|
-
const isDisplayDefault = head === DISPLAY_DEFAULT_PATH_HEAD && !!displayType && !!slot;
|
|
62
|
-
if (isDisplayDefault) {
|
|
63
|
-
session.setDisplayTypeDefault(displayType, slot, undefined);
|
|
64
|
-
}
|
|
65
|
-
return isDisplayDefault;
|
|
66
|
-
}
|