# SessionTracksManagerSessionMixin

Auto-generated from the @jbrowse/mobx-state-tree model in the source — see the [developer guide](https://jbrowse.org/jb2/docs/developer_guide/) for concepts. Built into JBrowse core. [View source](https://github.com/GMOD/jbrowse-components/blob/main/packages/product-core/src/Session/SessionTracks.ts).

Adds session tracks to a session, and stores the user's edits to any track
as a delta against its base config.

Each section ends with the members a composed model contributes, linked to the page that documents them.

## Properties

| Member | Description |
| --- | --- |
| **sessionTracks**<br><code>sessionTracks: types.stripDefault( types.array(pluginManager.pluggableConfigSchemaType('track')), [], )</code> | Tracks the session added, each entry the base its edits (trackConfigDeltas) diff against, as a config.json entry is for a config track. |
| **trackConfigDeltas**<br><code>trackConfigDeltas: types.stripDefault( types.frozen&lt;Record&lt;string, PlainTrackConfig&gt;&gt;(), {}, )</code> | Per-track config overrides, keyed by trackId, stored as a *delta* against the base config (the sessionTracks or jbrowse.tracks entry) rather than a full copy — so a later change to an untouched field of the base still flows through (see trackConfigDelta.ts). A `null` member resets a slot the base sets. An admin's edits land here too, and reach jbrowse.tracks only through `promoteTrackConfigDeltas`. Frozen (not a typed track array) on purpose: a typed create() would fill defaults, erasing the "unset vs default" distinction the delta merge relies on.<br><br>`stripDefault` for the reason every other persisted prop beside it has it: without it the empty map is written into every snapshot and every share link, so a session that never overrode a track still ships `"trackConfigDeltas":{}`. It was the one prop added since that convention without it. |

7 inherited properties from one model:

From [BaseSessionModel](../basesessionmodel): [`id`](../basesessionmodel#property-id), [`name`](../basesessionmodel#property-name), [`focusedViewId`](../basesessionmodel#property-focusedviewid), [`highlights`](../basesessionmodel#property-highlights), [`highlightsVisible`](../basesessionmodel#property-highlightsvisible), [`highlightLabelsVisible`](../basesessionmodel#property-highlightlabelsvisible), [`heldForMissingPlugins`](../basesessionmodel#property-heldformissingplugins)


## Volatiles

| Member | Description |
| --- | --- |
| **editableTrackConfigs**<br><code>Map&lt;string, EditableTrackConfig&gt;</code> | Per-track private working copies, keyed by trackId. A plain Map — not observable, not persisted — mirroring the pluginManager hydration cache: it holds the live MST config node a shown track's in-place quick-edits mutate, so the shared frozen base is never touched. See [ADR-032](https://github.com/GMOD/jbrowse-components/blob/main/agent-docs/architecture-decision-records/adr-032-track-config-nodes-are-throwaway-views.md).<br><br>Not evicted: it's a pure memoization cache, bounded by the count of distinct tracks shown this session (each entry a lazily-hydrated config node), holding no authoritative state — the persisted delta is the source of truth, and reset/programmatic edits keep a retained copy in sync. Retention is volatile RAM only (never serialized), so it's not worth a reference-counted prune at every track-removal path.<br><br>Each entry carries the resolved config it mirrors, so a delta or base replaced from outside this mixin invalidates it — see `getEditableTrackConfig`. |

6 inherited volatiles from 2 models:

From [BaseSessionModel](../basesessionmodel): [`selection`](../basesessionmodel#volatile-selection), [`hovered`](../basesessionmodel#volatile-hovered), [`queueOfDialogs`](../basesessionmodel#volatile-queueofdialogs), [`preferencesOverrides`](../basesessionmodel#volatile-preferencesoverrides)

From [SnackbarModel](../snackbarmodel): [`snackbarMessages`](../snackbarmodel#volatile-snackbarmessages), [`errorDialog`](../snackbarmodel#volatile-errordialog)


## Getters

| Member | Description |
| --- | --- |
| **trackBasesById**<br><code>Map&lt;string, TrackConfigEntry&gt;</code> | Each track's base by trackId: its sessionTracks entry, else its config.json entry. Rebuilt when either list changes, never on an edit. |
| **tracks**<br><code>TrackConfigEntry[]</code> | Session tracks first, then the config tracks, each with its edits. An edit copies the list of bases and lays each delta at its track's position, so past that copy it costs the count of edited tracks. |
| **promotableTrackIds**<br><code>string[]</code> | The edited tracks `promoteTrackConfigDeltas` can write: those whose base is a config.json entry. A session track's delta has no file to go to. |

13 inherited getters from 2 models:

From [BaseSessionModel](../basesessionmodel): [`root`](../basesessionmodel#getter-root), [`jbrowse`](../basesessionmodel#getter-jbrowse), [`rpcManager`](../basesessionmodel#getter-rpcmanager), [`configuration`](../basesessionmodel#getter-configuration), [`adminMode`](../basesessionmodel#getter-adminmode), [`textSearchManager`](../basesessionmodel#getter-textsearchmanager), [`assemblies`](../basesessionmodel#getter-assemblies), [`DialogComponent`](../basesessionmodel#getter-dialogcomponent), [`DialogProps`](../basesessionmodel#getter-dialogprops), [`animationMode`](../basesessionmodel#getter-animationmode), [`scrollZoom`](../basesessionmodel#getter-scrollzoom), [`numberGrouping`](../basesessionmodel#getter-numbergrouping)

From [SnackbarModel](../snackbarmodel): [`snackbarMessageSet`](../snackbarmodel#getter-snackbarmessageset)


## Methods

| Member | Description |
| --- | --- |
| **withTrackEdits**<br><code>(base: TrackConfigEntry) =&gt; TrackConfigEntry</code> | `base` with its delta (trackConfigDeltas) merged over it, or `base` itself by identity when it has none, which keeps the hydration cache warm. |
| **baseTrackConfig**<br><code>(trackId: string) =&gt; TrackConfigEntry &#124; undefined</code> | The entry `trackId` edits over, hydrated: the one the session added it with, or its config.json entry. What a display's "is this arranged" and "reset" compare its live config against. Per-id reactive, like `getTrackById`. |
| **getEditableTrackConfig**<br><code>(trackId: string, schemaType: IAnyType) =&gt; AnyConfigurationModel &#124; undefined</code> | The config node `trackId` resolves to: a live node as it stands, otherwise a private working copy of its current frozen (base+delta) config, so a shown track's in-place quick-edits (setSlot) mutate this copy and never the shared frozen base (see ADR-032). Called by TrackConfigurationReference during lazy hydration.<br><br>Cached against the resolved config it was built from, not by trackId alone. A write this mixin makes re-stamps the entry, so the copy an edit is still being typed into is never swapped out mid-keystroke; a delta or base replaced from outside — an undo's `applySnapshot` on the session, a session restore, a session track deleted and added again under its id — cannot, so the next read rebuilds the copy from what now resolves. Per-id reactive on the node rather than the config, so a display reading its config does not recompute when its own working copy is persisted. Per schema type as well, since an id re-added under another track type resolves through that type's reference. |
| **getTrackConfigChanges**<br><code>(trackId: string) =&gt; TrackConfigChange[]</code> | The overridden slots for `trackId` (empty when it has no delta): each changed setting's path, its base/default value and the edited value. Drives the "view changes" dialog opened from the edited badge. |
| **isTrackOverride**<br><code>(trackId: string) =&gt; boolean</code> | Whether `trackId` carries an edit over its base config, which drives the "Reset track settings" item and the edited badge. Changed slots, not mere presence in trackConfigDeltas: a delta can hold only content-free display stubs, which must not read as an override. |

7 inherited methods from 3 models:

From [TracksManagerSessionMixin](../tracksmanagersessionmixin): [`getTrackById`](../tracksmanagersessionmixin#method-gettrackbyid), [`getTracksById`](../tracksmanagersessionmixin#method-gettracksbyid)

From [BaseSessionModel](../basesessionmodel): [`getPreferenceDefault`](../basesessionmodel#method-getpreferencedefault), [`getPreference`](../basesessionmodel#method-getpreference), [`getPreferenceChanges`](../basesessionmodel#method-getpreferencechanges)

From [ReferenceManagementSessionMixin](../referencemanagementsessionmixin): [`getReferringMultiple`](../referencemanagementsessionmixin#method-getreferringmultiple), [`getReferring`](../referencemanagementsessionmixin#method-getreferring)


## Actions

| Member | Description |
| --- | --- |
| **addSessionTrackConf**<br><code>(trackConf: AnyConfiguration) =&gt; AnyTrackConfig &#124; undefined</code> | Add a track config to *this session*: it lands in `sessionTracks`, travels with the session when it is saved or shared, and never reaches the config.json the server hands every visitor.<br><br>**The default destination.** Everything that is not an Add-track workflow wants this one, whoever is looking — a session spec's `sessionTracks`, a URL's `&sessionTracks=`, and every track a feature stands up on the user's behalf. Mirrors `addSessionConnectionConf` in the connections mixins.<br><br>Returns the entry, which is the track's base: edit the track through `updateTrackConfiguration` or a display's `setConf`, not the entry. |
| **publishTrackConf**<br><code>(trackConf: AnyConfiguration) =&gt; any</code> | Publish a track config to the shared catalog if this user can, and fall back to their session if they cannot: an admin's goes to `jbrowse.tracks`, which the admin server writes back into the config.json every visitor is served; everyone else's goes to `sessionTracks`.<br><br>**Call it only from the "Add track" workflows**, where an admin adding a track means to add it for the whole site. For a track a feature creates on the user's behalf (a search result, a computed consensus, a reconstruction's segment labels), one admin click on this publishes it to every visitor, and each later click publishes another copy, because the per-launch trackId prevents deduplication. Use `addSessionTrackConf` above for those.<br><br>An admin's track still goes to the session when it names an assembly the config.json does not carry: a session spec's assembly, a MAF sample's genome, or a comparative view's synthesized pair. The Add-track widget takes its assembly from the containing view, so an admin adding a track in such a view passes a name no visitor can resolve. Publishing it would write an entry the server sends to every visitor and no visitor can draw. Adding it to the session keeps the track usable and writes no dangling entry; a snackbar names the assembly that caused the fallback.<br><br>**The snackbar names the assembly and not the track**, so a batch produces one message: `pushSnackbarMessage` dedupes on the exact text, and `BulkAddTracksWorkflow` publishes in a loop. Including the track name would show one snackbar per file to an admin adding thirty. The assembly is all the admin needs to act on. |
| **addTrackConf**<br><code>(trackConf: AnyConfiguration) =&gt; AnyTrackConfig &#124; undefined</code> | Deprecated alias of `addSessionTrackConf`. Call that, or `publishTrackConf`. |
| **updateTrackConfiguration**<br><code>(trackConf: PlainTrackConfig) =&gt; void</code> | Persist an edited track config as a delta (trackConfigDeltas) against its base, the sessionTracks or config.json entry — only the changed slots — so the edits persist, are shared, undo and reset, while changes to untouched fields of the base still flow through. An admin's edit is a delta like anyone's: it reaches the config.json the server hands every visitor only through `promoteTrackConfigDeltas`. An opened connection track defers to the base mixin, which routes it to connectionTrackConfigs. |
| **promoteTrackConfigDeltas**<br><code>(trackId?: string &#124; undefined) =&gt; void</code> | Write this session's track edits into the base configs — the config.json an admin server hands every visitor — and drop the deltas they were held in. One track's, or every track's when `trackId` is omitted, of `promotableTrackIds`: a session track's edits stay in the session. An admin's alone: anyone else's base is the in-memory copy of a file they cannot write. |
| **resetTrackConfiguration**<br><code>(trackId: string) =&gt; void</code> | Drop a track's delta (trackConfigDeltas) so it reverts to its base, the sessionTracks or jbrowse.tracks entry. Unlike deleteTrackConf this does not dereference the track from open views — the base config re-resolves in place, so an open track stays open and simply reverts. |
| **deleteTrackConf**<br><code>(trackConf: AnyTrackConfig) =&gt; (PluggableConfigNode &amp; IStateTreeNode&lt;PluggableConfigSchemaType&gt;)[] &#124; undefined</code> |  |

25 inherited actions from 3 models:

From [BaseSessionModel](../basesessionmodel): [`setSelection`](../basesessionmodel#action-setselection), [`clearSelection`](../basesessionmodel#action-clearselection), [`setHovered`](../basesessionmodel#action-sethovered), [`setHighlightsVisible`](../basesessionmodel#action-sethighlightsvisible), [`setHighlightLabelsVisible`](../basesessionmodel#action-sethighlightlabelsvisible), [`addHighlight`](../basesessionmodel#action-addhighlight), [`removeHighlight`](../basesessionmodel#action-removehighlight), [`updateHighlight`](../basesessionmodel#action-updatehighlight), [`setHighlights`](../basesessionmodel#action-sethighlights), [`setPreferenceOverride`](../basesessionmodel#action-setpreferenceoverride), [`clearPreferenceOverrides`](../basesessionmodel#action-clearpreferenceoverrides), [`clearPreferenceOverride`](../basesessionmodel#action-clearpreferenceoverride), [`setScrollZoom`](../basesessionmodel#action-setscrollzoom), [`setName`](../basesessionmodel#action-setname), [`setFocusedViewId`](../basesessionmodel#action-setfocusedviewid), [`removeActiveDialog`](../basesessionmodel#action-removeactivedialog), [`queueDialog`](../basesessionmodel#action-queuedialog), [`removeDialog`](../basesessionmodel#action-removedialog)

From [SnackbarModel](../snackbarmodel): [`notify`](../snackbarmodel#action-notify), [`notifyError`](../snackbarmodel#action-notifyerror), [`setErrorDialog`](../snackbarmodel#action-seterrordialog), [`pushSnackbarMessage`](../snackbarmodel#action-pushsnackbarmessage), [`popSnackbarMessage`](../snackbarmodel#action-popsnackbarmessage), [`removeSnackbarMessage`](../snackbarmodel#action-removesnackbarmessage)

From [ReferenceManagementSessionMixin](../referencemanagementsessionmixin): [`dereferenceTrack`](../referencemanagementsessionmixin#action-dereferencetrack)


