Files
dc/client/src/app/_globals.ts
T
dc 88010c3980
Build / Build-and-ng-test (pull_request) Failing after 1m55s
Build / Build-and-test-development (pull_request) Skipped
Lighthouse Checks / lighthouse (pull_request) Successful in 20m22s
feat(embed): resolve va_parmap values through named date anchors
A VA parameter can now carry a transform on the column side of a mapping:

  va_parmap=SELECTED_DATE-D_DATE:ADD(QUARTER_START,-1)

which filters D_DATE on the report value AND the same point one quarter
earlier, as a single IN clause - so the AND rule, the clause signature,
saveQuery and the reload loop are untouched.

Transforms resolve to one clause with these operations:

- ADD(<ANCHOR>,<offset>)   the value plus one anchor beside it -> IN
- RANGE(<PERIOD>,<offset>) a closed period -> BETWEEN

Anchors: QUARTER_START/END, MONTH_START/END, YEAR_START/END.
Periods: QUARTER, MONTH, YEAR. Offset is a whole number of periods,
defaulting to 0.

The names describe the result rather than mirroring SAS intnx: the
arithmetic runs in the browser, so mirroring intnx would mean
reimplementing its alignment letters and their corners (week alignment,
's' and 'm') with no guarantee of matching SAS. A report author can read
ADD(QUARTER_START,-1) without knowing intnx.

Resolution is anchored on the parameter value, never on today, so a saved
report reproduces the same rows. A transform that cannot run where it is
used - a non-temporal column, a value that is not a date - is skipped and
reported in the existing warning banner rather than silently filtering on
the raw value.
2026-10-28 11:52:53 +00:00

182 lines
4.7 KiB
TypeScript

import { QueryClause } from './models/TableData'
import { VaParmapTarget } from './shared/utils/parse-va-parmap'
/**
* Filtering cache info, to be reused when filtering modal is re-open
*/
interface FilterCache {
cols: any[]
vals: any[]
groupLogic: string
whereClause: string
libds: string
clauses: any[]
query: QueryClause[]
}
/**
* Filtering cache info in the open viewboxes, to be reused when filtering modal is re-open
*/
interface ViewboxCache {
[key: number]: {
filter: FilterCache
}
}
/**
* Initial values when no cached values stored
*/
export const initFilter: { filter: FilterCache } = {
filter: {
cols: <any[]>[],
vals: <any[]>[],
groupLogic: <string>'',
whereClause: <string>'',
libds: <string>'',
clauses: <any>[],
query: <QueryClause[]>[]
}
}
export interface XLMapListItem {
id: string
description: string
targetDS: string
}
export interface HandsontableStaticConfig {
darkTableHeaderClass: string
}
/**
* Cached filtering values across whole app (editor, viewer, viewboxes)
* Cached lineage libraries, tables
* Cached metadata tree
* Cached usernav tree
* Cached viyaApi collections, search and selected endpoint
*/
export const globals: {
embed: boolean | 'va'
/**
* VA embed filter behavior: 'live' = auto-apply, 'confirm' = manual Apply.
* Defaults to 'live'; toggled by the Auto-apply checkbox in the editor.
*/
vaApplyMode: 'live' | 'confirm'
/**
* Explicit VA parameter -> DC column mappings, parsed from the `va_parmap`
* URL parameter (see parseVaParmap). Empty unless configured; entries override
* VA's default same-name (parameter label -> column) resolution, so two DC
* instances over one table can filter the same column from differently-named
* VA parameters.
*/
vaParamMap: Map<string, VaParmapTarget>
/**
* `va_parmap` entries that could not be used at all (not a plain SAS column
* name, or missing a side of the `-`). Surfaced to the report author, because
* these are hand-written in the report's URL and a typo otherwise looks like
* a working, unfiltered view.
*/
vaParmapProblems: string[]
rootParam: string
dcLib: string
xlmaps: XLMapListItem[]
editor: any
viewer: any
viewboxes: ViewboxCache
lineage: any
metadata: any
viyaApi: any
usernav: any
operators: any
handsontable: HandsontableStaticConfig
[key: string]: any
} = {
embed: false,
vaApplyMode: 'live',
vaParamMap: new Map(),
vaParmapProblems: [],
rootParam: <string>'',
dcLib: '',
xlmaps: [],
editor: {
startupSet: <boolean>false,
treeNodeLibraries: <any[] | null>[],
libsAndTables: <any[]>[],
libraries: <string[] | undefined>[],
library: <string>'',
table: <string>'',
filter: <FilterCache>{
cols: <any[]>[],
vals: <any[]>[],
groupLogic: <string>'',
whereClause: <string>'',
libds: <string>'',
clauses: <any>[],
query: <QueryClause[]>[]
}
},
viewer: {
startupSet: <boolean>false,
tablesSet: <boolean>false,
libraries: <any[]>[],
tables: <any>null,
library: '',
table: '',
libinfo: [],
librariesSearch: <string>'',
filter: <FilterCache>{
cols: <any[]>[],
vals: <any[]>[],
groupLogic: <string>'',
whereClause: <string>'',
libds: <string>'',
clauses: <any>[],
query: <QueryClause[]>[]
},
currentSelection: <string>''
},
viewboxes: {},
lineage: {
libraryList: <any[] | undefined>[],
tablesList: <any[] | undefined>[],
columnsList: <any[] | undefined>[],
librariesSearch: <string>'',
lib: <String | null>'',
table: <String | undefined>'',
column: <String | undefined>'',
currentLineagePathLibTable: <String>'',
currentLineagePathColumn: <String>''
},
metadata: {
metaDataList: <any[] | undefined>undefined,
metaDataSearch: <string>'',
metaObjectList: <any[] | undefined>[],
metaObjectSearch: <string>'',
metaRepositories: <any[] | undefined>undefined,
selectedRepository: <string>''
},
viyaApi: {
collectionsList: <any[] | undefined>undefined,
collectionsSearch: <string>'',
selectedRepository: <string>''
},
usernav: {
userList: <any[] | undefined>undefined,
userSearch: <string>'',
groupList: <any[] | undefined>undefined,
groupSearch: <string>'',
roleList: <any[] | undefined>undefined,
roleSearch: <string>''
},
operators: {
numOperators: ['=', '<', '>', '<=', '>=', 'BETWEEN', 'IN', 'NOT IN', 'NE'],
charOperators: ['=', '<', '>', '<=', '>=', 'CONTAINS', 'IN', 'NOT IN', 'NE']
},
handsontable: {
darkTableHeaderClass: 'darkTH'
},
userDropdownConfig: {
closeOnDebugClick: false
}
}