diff --git a/src/application/app-preferences.ts b/src/application/app-preferences.ts index 1124b2c6..f79e5b4d 100644 --- a/src/application/app-preferences.ts +++ b/src/application/app-preferences.ts @@ -8,9 +8,8 @@ // Narrow scope (plan review): this service owns ONLY the persist half of // each preference. Every write site except `toggleTheme` already mutates its // own state field itself (splitters.ts sets `ctx.state.sidebarPx` before -// calling `ctx.save(...)`; dashboard.ts sets `state.dashLayout`/`dashCols` -// before calling `app.prefs.save(...)` directly — #276 Phase 5 deleted the -// flat `App.savePref` delegate; app.ts's `setResultRowLimit` sets +// calling `ctx.save(...)`; #276 Phase 5 deleted the flat `App.savePref` +// delegate; app.ts's `setResultRowLimit` sets // `state.resultRowLimit` first) — so `save(name, value)` is a pure typed // persist call, no state slice needed. `toggleTheme` is the one exception // (issue ruling): the state flip AND the persist happen together here: the @@ -29,7 +28,7 @@ import { KEYS } from '../state.js'; * untouched by this service. */ export type PreferenceKey = | 'theme' | 'sidebarPx' | 'editorPct' | 'sideSplitPct' | 'cellDrawerPx' - | 'sidePanel' | 'resultRowLimit' | 'dashLayout' | 'dashCols' + | 'sidePanel' | 'resultRowLimit' // #313 — the documentation pane's own persisted resize width, a sibling of // cellDrawerPx (never shared with it — see splitters.ts's 'docPane' axis). | 'docPanePx'; @@ -48,7 +47,7 @@ export interface AppPreferencesDeps { export interface AppPreferences { /** Generic persist-only setter — the exact `(name, value)` shape app.ts's * former `App.savePref` delegate used to expose (#276 Phase 5 deleted it; - * dashboard.ts/saved-history.ts/splitters.ts's callers call `app.prefs.save` + * saved-history.ts/splitters.ts's callers call `app.prefs.save` * directly now). This IS the service's write API: per-key typed setters * were considered and dropped (review) — every real call site already * holds a validated `{name, value}` pair, so a per-key surface would ship diff --git a/src/core/dashboard.ts b/src/core/dashboard.ts index 46963aef..4a37fff7 100644 --- a/src/core/dashboard.ts +++ b/src/core/dashboard.ts @@ -7,66 +7,6 @@ // tiles stream through the shared `app.exec.executeRead` seam as of #193/#276, so the // former `FORMAT JSON` → array-rows transform and its SQL prep were retired.) -/** - * Dashboard layout modes (#149 D2, #184): `arrange` = uniform multi-column grid - * (default, column count from `dashCols`), `report` = single centered column - * (1100px) with taller tiles, `wide` = one tile per row filling the full - * available dashboard width (#184, Grafana-style). Persisted per browser - * (`asb:dashLayout`); `wide` extends the key rather than migrating it, so - * existing arrange/report selections stay valid. The four *effective* views the - * UI exposes are derived by `activeDashboardView` below (wide, report, and - * arrange split into its 2- and 3-column cases). - */ -export const DASH_LAYOUTS: readonly string[] = ['arrange', 'report', 'wide']; - -/** Snap a persisted layout to a known mode, defaulting to `arrange`. Pure. */ -export function normalizeDashLayout(v?: string | null): string { - return v != null && DASH_LAYOUTS.includes(v) ? v : 'arrange'; -} - -/** Column-count options for Arrange mode (persisted `asb:dashCols`). */ -export const DASH_COLS: readonly number[] = [2, 3]; - -/** Snap a persisted column count to 2 or 3, defaulting to 3. Pure. */ -export function normalizeDashCols(n?: number | null): number { - return n != null && DASH_COLS.includes(n) ? n : 3; -} - -// The two persisted keys `activeDashboardView`/`dashboardViewSelection` read -// and write — kept structural (rather than importing state.js's full State -// type) since only these two fields are ever touched here. -interface DashLayoutState { - dashLayout?: string; - dashCols?: number; -} - -/** - * The four-way layout switcher's active value (#184), derived from the two - * persisted keys so a single control can drive them: `wide` and `report` map - * straight through; `arrange` splits into `columns-2`/`columns-3` by `dashCols`. - * Pure — the UI's segmented control reads this to mark exactly one button - * active, and `dashboardViewSelection` is its inverse (view → state changes). - */ -export function activeDashboardView(state: DashLayoutState): 'wide' | 'report' | 'columns-2' | 'columns-3' { - if (state.dashLayout === 'wide') return 'wide'; - if (state.dashLayout === 'report') return 'report'; - return state.dashCols === 2 ? 'columns-2' : 'columns-3'; -} - -/** - * Inverse of `activeDashboardView` (#184): the `{dashLayout, dashCols?}` a - * picked switcher value implies. `dashCols` is present only for the column - * views (the caller persists just the keys that actually changed, so choosing a - * column count never rewrites `dashLayout` when it is already `arrange`, and - * vice-versa). An unrecognized view falls back to the default `columns-3`. - */ -export function dashboardViewSelection(view?: string | null): DashLayoutState { - if (view === 'wide') return { dashLayout: 'wide' }; - if (view === 'report') return { dashLayout: 'report' }; - if (view === 'columns-2') return { dashLayout: 'arrange', dashCols: 2 }; - return { dashLayout: 'arrange', dashCols: 3 }; -} - /** * Rows kept per dashboard tile (#149 D9). Preserves the 5000-point line/area * chart cap (`CHART_ROW_CAPS` in `src/core/chart-data.js`) — a fetch cap below diff --git a/src/core/schema-cards.ts b/src/core/schema-cards.ts index bcba77d5..6c5e588d 100644 --- a/src/core/schema-cards.ts +++ b/src/core/schema-cards.ts @@ -141,14 +141,11 @@ function numberish(v: number | string | undefined): number | null { * they belong in the detail drawer, not in card geometry. `comment` (trimmed, * untruncated) isn't drawn as its own row — like the plain inline graph, it's a * hover-only tooltip on the whole card, so it never affects the card's own layout. - * `_legacySkipIndexes` is never read — a bygone skip-index-rows argument some - * callers still pass; accepted and ignored so it can never affect the model. */ export function buildCardModel( node?: CardGraphNode | null, tableRow?: CardTableRow | null, columns?: SchemaCardColumnRow[] | null, - _legacySkipIndexes?: unknown, ): CardModel { const n = node || {}; const tr = tableRow || {}; diff --git a/src/core/spec-draft.ts b/src/core/spec-draft.ts index d7eb0731..059bf4d8 100644 --- a/src/core/spec-draft.ts +++ b/src/core/spec-draft.ts @@ -5,9 +5,6 @@ import { cloneJson } from './saved-query.js'; import { createQuerySpecValidationService as _createQuerySpecValidationService, - // Kept for parity with the pre-conversion module — unused here, same as - // before (spec-schema.js's own export, consumed directly by other modules). - querySpecSchemaService, } from './spec-schema.js'; import type { QuerySpecV1 } from '../generated/json-schema.types.js'; import { hasSameTimeRangeParameter } from './query-time-range.js'; diff --git a/src/net/ch-client.ts b/src/net/ch-client.ts index d2574a7a..50e2825c 100644 --- a/src/net/ch-client.ts +++ b/src/net/ch-client.ts @@ -892,8 +892,6 @@ export async function exportQuery(ctx: ChCtx, sql: string, opts: ExportQueryOpti * (e.g. multiquery SELECTs pass their own cap + session_id) * @param onLine called per parsed stream object in streaming mode * @param onChunk called once per read chunk in streaming mode - * @param onRaw unused by `runQuery` itself — the caller reads `.raw` off the - * returned result instead; kept for parity with the original docstring */ export interface RunQueryOptions { format?: string; @@ -903,7 +901,6 @@ export interface RunQueryOptions { params?: Record; onLine?: (line: StreamLine) => void; onChunk?: () => void; - onRaw?: (text: string) => void; } /** `runQuery`'s result: a query error, a raw-mode body, or a completed stream. */ @@ -916,12 +913,12 @@ export interface RunQueryResult { /** * Run a query in streaming mode (JSONStringsEachRowWithProgress) or raw mode * (TSV/JSON). `onLine(parsedObj)` is called per stream object in streaming - * mode; `onRaw(text)` once for raw mode. Returns { error } or { raw } shape via + * mode. Returns { error } or { raw } shape via * the result object the caller passes in `apply`. * * @param ctx * @param sql - * @param o { format, signal, resultRowLimit, params, onLine(json), onChunk(), onRaw(text) } + * @param o { format, signal, resultRowLimit, params, onLine(json), onChunk() } * `resultRowLimit` caps a normal result server-side (max_result_rows + * result_overflow_mode); `params` are extra query-string options that ride * alongside query_id (e.g. multiquery SELECTs pass their own cap + session_id). diff --git a/src/state.ts b/src/state.ts index 4b56cb13..150de7f6 100644 --- a/src/state.ts +++ b/src/state.ts @@ -9,7 +9,6 @@ import { } from './core/saved-query.js'; import type { QueryRoot } from './core/saved-query.js'; import { decodeStoredSavedQueries as decodeStoredSavedQueriesUntyped } from './core/library-codec.js'; -import { normalizeDashLayout, normalizeDashCols } from './core/dashboard.js'; import { loadJSON as loadJSONUntyped, saveJSON as saveJSONUntyped, loadStr as loadStrUntyped, @@ -351,8 +350,6 @@ export interface AppState { theme: string; density: string; resultRowLimit: number; - dashLayout: string; - dashCols: number; sidebarPx: number; editorPct: number; sideSplitPct: number; @@ -495,8 +492,6 @@ export const KEYS = { * on purpose: the concept it names is still live, it is not a Dashboard * variable, and this is a persisted key besides. */ filterActive: 'asb:filterActive', - dashLayout: 'asb:dashLayout', - dashCols: 'asb:dashCols', varRecent: 'asb:varRecent', varRecentDisabled: 'asb:varRecentDisabled', /** Isolated per-dashboard Dashboard-variable persistence (#303 Option B) — a @@ -634,11 +629,6 @@ export function createState(read: StateReader = { loadJSON, loadStr }): AppState // One persisted preference, default 500; a non-option stored value snaps // back to the default so the selector always reflects a real choice. resultRowLimit: normalizeRowLimit(parseInt(read.loadStr(KEYS.resultRowLimit, '500'), 10)), - // Dashboard layout prefs (#149 D2), persisted per browser. Plain (non-signal) - // like theme/density — the standalone dashboard page reads them at build time - // and mutates + re-saves on the Arrange/Report + column-count controls. - dashLayout: normalizeDashLayout(read.loadStr(KEYS.dashLayout, 'arrange')), - dashCols: normalizeDashCols(parseInt(read.loadStr(KEYS.dashCols, '3'), 10)), sidebarPx: clamp(parseInt(read.loadStr(KEYS.sidebarPx, '248'), 10), 180, 420), editorPct: num(KEYS.editorPct, 45, 15, 85), sideSplitPct: num(KEYS.sideSplitPct, 58, 25, 85), diff --git a/src/styles.css b/src/styles.css index d2426aee..6d7a4a88 100644 --- a/src/styles.css +++ b/src/styles.css @@ -371,7 +371,7 @@ body { the UA defaults converts "forgot to style a heading" from a visible bug into a quiet inherit, and forces any real step up the ramp to be deliberate. Rules that DO size a heading (.md-view, .modal-card, .schema-detail, .dash-notfound-title, - .docs-name, .detached-title, .section-label, .login-h1) all out-specify this. */ + .docs-name, .detached-title, .section-label) all out-specify this. */ h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: var(--fw-semibold); @@ -456,8 +456,6 @@ h1, h2, h3, h4, h5, h6 { .login-brand-text { display: flex; flex-direction: column; line-height: var(--lh-tight); } .login-brand-name { font-size: var(--text-headline); font-weight: var(--fw-semibold); color: var(--fg); } .login-brand-sub { font-size: var(--text-label); color: var(--fg-faint); } -.login-h1 { font-size: var(--text-doc-h1); font-weight: var(--fw-semibold); letter-spacing: -.3px; color: var(--fg); margin-bottom: 4px; } -.login-sub { font-size: var(--text-body); color: var(--fg-mute); margin-bottom: 20px; line-height: var(--lh-body); } /* SSO section */ .login-sso { display: flex; flex-direction: column; gap: 8px; } @@ -579,13 +577,6 @@ h1, h2, h3, h4, h5, h6 { flex-shrink: 0; } .logo-name { font-size: var(--text-body); font-weight: var(--fw-semibold); color: var(--fg); } -.env-chip { - font-size: var(--text-label); color: var(--fg-faint); - padding: 2px 6px; - background: var(--bg-chip); - border-radius: var(--r-sm); - font-family: var(--mono); -} .conn-status { display: flex; align-items: center; gap: 6px; font-size: var(--text-label); color: var(--fg-mute); @@ -607,11 +598,6 @@ h1, h2, h3, h4, h5, h6 { flex-shrink: 0; } .conn-status.dim::before { background: var(--fg-faint); box-shadow: none; } -.user-email { - font-size: var(--text-label); color: var(--fg-mute); - font-family: var(--mono); - max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; -} .hd-btn { width: 26px; height: 26px; border: none; background: transparent; @@ -659,7 +645,6 @@ h1, h2, h3, h4, h5, h6 { } /* ------------ header File menu + library title ------------ */ -.hd-divider { width: 1px; height: 18px; background: var(--border); flex-shrink: 0; } .hd-file-btn { display: flex; align-items: center; gap: 5px; height: 26px; padding: 0 8px; border: none; border-radius: var(--r-sm); background: transparent; color: var(--fg-mute); @@ -733,10 +718,6 @@ h1, h2, h3, h4, h5, h6 { margin-top: 4px; padding: 8px 12px; border-top: 1px solid var(--border-faint); font-size: var(--text-micro); color: var(--fg-faint); font-family: var(--mono); } -/* Variable history (#171): a `.fm-item`-styled