Refine route-scoped tape subscriptions and table virtualization

- Scope live channels by route and trim unused feed work
- Switch tape tables to fixed-height virtual rows with separate scroll containers
- Add tests for route feature maps and virtual config
This commit is contained in:
dirtydishes 2026-05-07 22:03:09 -04:00
parent bb1df9b58b
commit 9c351d12d1
5 changed files with 955 additions and 582 deletions

View file

@ -956,17 +956,27 @@ h3 {
.data-table-wrap {
flex: 1 1 auto;
min-height: 0;
overflow: auto;
overflow-x: auto;
overflow-y: hidden;
border-top: 1px solid var(--border);
border-bottom: 1px solid var(--border);
background: rgba(5, 8, 12, 0.42);
}
.data-table {
display: block;
display: flex;
flex-direction: column;
min-height: 0;
min-width: 980px;
}
.data-table-scroll {
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
}
.data-table-body {
position: relative;
min-width: 100%;
@ -1004,10 +1014,8 @@ h3 {
}
.data-table-head {
position: sticky;
top: 0;
z-index: 2;
min-height: 30px;
flex: 0 0 auto;
height: 30px;
padding: 0 10px;
border-bottom: 1px solid rgba(255, 255, 255, 0.095);
background: rgba(8, 11, 16, 0.98);
@ -1019,7 +1027,7 @@ h3 {
.data-table-row {
width: 100%;
min-height: 40px;
height: 40px;
padding: 0 10px;
border: 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.055);
@ -1035,6 +1043,7 @@ h3 {
.data-table-virtual-row {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
@ -1050,18 +1059,18 @@ h3 {
}
.data-table-row-options {
min-height: 36px;
height: 36px;
}
.data-table-row-equities {
min-height: 34px;
height: 36px;
}
.data-table-row-flow,
.data-table-row-alerts,
.data-table-row-classifier,
.data-table-row-dark {
min-height: 44px;
height: 44px;
}
.data-table-row-classified {

View file

@ -19,12 +19,15 @@ import {
getOptionTableSnapshot,
getLiveFeedStatus,
getLiveManifest,
getRouteFeatures,
getTapeVirtualConfig,
mergeNewestWithOverflow,
normalizeAlertSeverity,
nextFlowFilterPopoverState,
projectPausableTapeState,
reducePausableTapeData,
shouldRetainLiveSnapshotHistory,
shouldIncludeEquitiesForDarkUnderlyingFallback,
shouldShowEquitiesSilentFeedWarning,
selectPrimaryClassifierHit,
smartMoneyProfileLabel,
@ -51,15 +54,13 @@ const makeAlert = (overrides: Record<string, unknown> = {}) =>
}) as any;
describe("live manifest", () => {
it("includes options on home and tape", () => {
it("includes only tape channels on /tape", () => {
const filters = buildDefaultFlowFilters();
for (const pathname of ["/", "/tape"]) {
expect(
getLiveManifest(pathname, "SPY", 60000, filters).some(
(subscription) => subscription.channel === "options"
)
).toBe(true);
}
const channels = getLiveManifest("/tape", "SPY", 60000, filters).map(
(subscription) => subscription.channel
);
expect(channels).toEqual(["options", "nbbo", "equities", "flow"]);
});
it("dedupes tape options subscription", () => {
@ -72,37 +73,29 @@ describe("live manifest", () => {
expect(tapeOptionsSubscriptions).toHaveLength(1);
});
it("keeps option filters on baseline subscription across page changes", () => {
it("keeps option filters on /tape options subscriptions", () => {
const filters = {
...buildDefaultFlowFilters(),
minNotional: 125_000
};
const homeOptionsSubscription = getLiveManifest("/", "SPY", 60000, filters).find(
(subscription) => subscription.channel === "options"
);
const tapeOptionsSubscription = getLiveManifest("/tape", "SPY", 60000, filters).find(
(subscription) => subscription.channel === "options"
);
expect(homeOptionsSubscription?.filters).toBe(filters);
expect(tapeOptionsSubscription?.filters).toBe(filters);
});
it("applies global flow filters to flow subscriptions on home and tape", () => {
it("applies global flow filters to flow subscriptions on /tape", () => {
const filters = {
...buildDefaultFlowFilters(),
minNotional: 50_000
};
const homeFlowSubscription = getLiveManifest("/", "SPY", 60000, filters).find(
(subscription) => subscription.channel === "flow"
);
const tapeFlowSubscription = getLiveManifest("/tape", "SPY", 60000, filters).find(
(subscription) => subscription.channel === "flow"
);
expect(homeFlowSubscription?.filters).toBe(filters);
expect(tapeFlowSubscription?.filters).toBe(filters);
});
@ -131,6 +124,90 @@ describe("live manifest", () => {
expect(optionsSubscription?.option_contract_id).toBe("AAPL-2025-01-17-200-C");
expect(equitiesSubscription?.underlying_ids).toEqual(["AAPL"]);
});
it("scopes /signals subscriptions to signals channels only", () => {
const channels = getLiveManifest("/signals", "SPY", 60000, buildDefaultFlowFilters()).map(
(subscription) => subscription.channel
);
expect(channels).toEqual([
"alerts",
"smart-money",
"classifier-hits",
"inferred-dark",
"equity-joins"
]);
});
it("scopes /charts subscriptions to chart channels only", () => {
const channels = getLiveManifest("/charts", "SPY", 60000, buildDefaultFlowFilters()).map(
(subscription) => subscription.channel
);
expect(channels).toEqual([
"smart-money",
"inferred-dark",
"equity-joins",
"equity-candles",
"equity-overlay"
]);
});
});
describe("route feature map", () => {
it("maps /tape to tape panes and dependencies", () => {
const features = getRouteFeatures("/tape");
expect(features.showOptionsPane).toBe(true);
expect(features.showEquitiesPane).toBe(true);
expect(features.showFlowPane).toBe(true);
expect(features.needsClassifierDecor).toBe(true);
expect(features.alerts).toBe(false);
});
it("maps /signals to signal panes and dependencies", () => {
const features = getRouteFeatures("/signals");
expect(features.showAlertsPane).toBe(true);
expect(features.showClassifierPane).toBe(true);
expect(features.showDarkPane).toBe(true);
expect(features.options).toBe(false);
expect(features.equityJoins).toBe(true);
});
it("maps /charts to chart panes and dependencies", () => {
const features = getRouteFeatures("/charts");
expect(features.showChartPane).toBe(true);
expect(features.showFocusPane).toBe(true);
expect(features.equityCandles).toBe(true);
expect(features.equityOverlay).toBe(true);
expect(features.alerts).toBe(false);
});
});
describe("fixed tape virtualization config", () => {
it("uses expected fixed row heights and overscan by table", () => {
expect(getTapeVirtualConfig("options")).toEqual({ rowHeight: 36, overscan: 24, debugLabel: "options" });
expect(getTapeVirtualConfig("equities")).toEqual({ rowHeight: 36, overscan: 20, debugLabel: "equities" });
expect(getTapeVirtualConfig("flow")).toEqual({ rowHeight: 44, overscan: 16, debugLabel: "flow" });
expect(getTapeVirtualConfig("alerts")).toEqual({ rowHeight: 44, overscan: 16, debugLabel: "alerts" });
expect(getTapeVirtualConfig("classifier")).toEqual({ rowHeight: 44, overscan: 16, debugLabel: "classifier" });
expect(getTapeVirtualConfig("dark")).toEqual({ rowHeight: 44, overscan: 16, debugLabel: "dark" });
});
});
describe("dark underlying route dependency helper", () => {
it("does not keep extra equities subscriptions when joins+trace fallback are sufficient", () => {
expect(shouldIncludeEquitiesForDarkUnderlyingFallback()).toBe(false);
expect(
getLiveManifest("/signals", "SPY", 60000, buildDefaultFlowFilters()).some(
(subscription) => subscription.channel === "equities"
)
).toBe(false);
expect(
getLiveManifest("/charts", "SPY", 60000, buildDefaultFlowFilters()).some(
(subscription) => subscription.channel === "equities"
)
).toBe(false);
});
});
describe("terminal navigation", () => {

File diff suppressed because it is too large Load diff

6
deploy-branch.sh Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
git fetch
git pull
docker compose up -d --build --force-recreate

7
deploy.sh Executable file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
git fetch
git switch deployment
git pull
docker compose up -d --build --force-recreate