react-semaphor 0.1.546 → 0.1.547
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/dist/analytics-protocol/index.js +70 -67
- package/dist/assistant-context/index.js +1 -1
- package/dist/briefings/index.js +1 -1
- package/dist/chunks/applied-constraints-DU-wndZ7.js +47 -0
- package/dist/chunks/{assistant-chat-BPXhulAx.js → assistant-chat-CK84cPAB.js} +106 -106
- package/dist/chunks/{bookmark-state-C4vetoa0.js → bookmark-state-Cu-a5ie_.js} +2 -8
- package/dist/chunks/{custom-visual-inputs-CkJW9pBS.js → custom-visual-inputs-ChL54gGm.js} +1 -1
- package/dist/chunks/{dashboard-C3CoKbGY.js → dashboard-DCk26-6i.js} +1 -1
- package/dist/chunks/{dashboard-briefing-launcher-Be4h-7My.js → dashboard-briefing-launcher-CQ1eYsGy.js} +528 -528
- package/dist/chunks/{dashboard-controls-bxPrlSyp.js → dashboard-controls-BMeZjF7r.js} +45 -45
- package/dist/chunks/{dashboard-json-BrjxIiRt.js → dashboard-json-BZqCoanC.js} +1 -1
- package/dist/chunks/{document-dashboard-inputs-CRVHpIHp.js → document-dashboard-inputs-tYd7ao0o.js} +94 -94
- package/dist/chunks/{edit-dashboard-visual-DYYYDjY6.js → edit-dashboard-visual-Bv3MHM_G.js} +281 -281
- package/dist/chunks/{column-catalog-BYnochWQ.js → filter-reach-copy-CGWsL_ez.js} +978 -861
- package/dist/chunks/{global-date-filter-utils-9d6m9-FE.js → global-date-filter-utils-BhAu8zIM.js} +4070 -3792
- package/dist/chunks/{index-DkQkMKa1.js → index-DmrLP5Ro.js} +30 -30
- package/dist/chunks/{raw-temporal-presentation-CBzrDOjM.js → raw-temporal-presentation-DypB7sMX.js} +1 -1
- package/dist/chunks/{report-preferences-dialog-4QEZWe5U.js → report-preferences-dialog-DoVyriYC.js} +59 -59
- package/dist/chunks/{resolve-dashboard-input-context-UpK_LBpL.js → resolve-dashboard-input-context-D0JDUa4h.js} +1511 -1612
- package/dist/chunks/{saved-dashboard-context-D_I3Lxk0.js → saved-dashboard-context-BfAH5j4L.js} +5 -5
- package/dist/chunks/{semaphor-ready-indicator-4zpRHE-X.js → semaphor-ready-indicator-CRm17oIP.js} +37137 -36459
- package/dist/chunks/{shelf-drop-preview-context-Cfw7TRAx.js → shelf-drop-preview-context-vy6P9THz.js} +80 -80
- package/dist/chunks/{table-settings-CunhoDUi.js → table-settings-WysCBj62.js} +133 -124
- package/dist/chunks/{use-create-flow-overlay-state-DZBZiiD-.js → use-create-flow-overlay-state-Csx_Xjsh.js} +2 -2
- package/dist/dashboard/index.js +2 -2
- package/dist/dashboard-authoring/index.js +1419 -1340
- package/dist/index.js +14 -14
- package/dist/surfboard/index.js +2 -2
- package/dist/types/components/surfboard/filter/types.d.ts +7 -0
- package/dist/types/components/surfboard/screen-size-preview-button.d.ts +7 -4
- package/dist/types/components/visual/matrix-table/matrix-card-view.d.ts +3 -0
- package/dist/types/index.js +2 -2
- package/dist/types/lib/dashboard-inputs/dashboard-filter-mapping-authoring.d.ts +346 -21
- package/dist/types/lib/dashboard-inputs/dashboard-filter-value-identity.d.ts +65 -0
- package/dist/types/lib/dashboard-inputs/resolve-selection-input.d.ts +3 -3
- package/dist/types/lib/hooks/use-dashboard-card.d.ts +2 -0
- package/dist/types/lib/matrix-table/matrix-delivery-policy.d.ts +1 -1
- package/dist/types/lib/matrix-table/matrix-runtime-types.d.ts +9 -1
- package/dist/types/lib/matrix-table/matrix-runtime.d.ts +5 -1
- package/dist/types/lib/query-context/dashboard-filter-mapping-resolution.d.ts +83 -13
- package/dist/types/lib/stores/dashboard-store.d.ts +12 -0
- package/dist/types/shared/analytics-protocol/applied-constraints.d.ts +57 -1
- package/dist/types/shared/assistant-protocol/context.d.ts +8 -8
- package/dist/types/shared/dashboard-authoring/changes/diagnostics.d.ts +2 -0
- package/dist/types/shared/dashboard-authoring/changes/resolve-dashboard-changes.d.ts +7 -0
- package/dist/types/shared/dashboard-authoring/click-to-filter-settings.d.ts +3 -3
- package/dist/types/shared/dashboard-authoring/dashboard-filter-automatic-target.d.ts +4 -4
- package/dist/types/shared/dashboard-authoring/dashboard-filter-mapping-contract.d.ts +3 -1
- package/dist/types/shared/dashboard-authoring/dashboard-filter-mapping-types.d.ts +27 -1
- package/dist/types/shared/dashboard-authoring/dashboard-filter-value-compatibility.d.ts +12 -3
- package/dist/types/shared/dashboard-authoring/filter-reach-copy.d.ts +18 -0
- package/dist/types/shared/dashboard-authoring/filter-reach-preview.d.ts +97 -0
- package/dist/types/shared/dashboard-authoring/index.d.ts +5 -1
- package/dist/types/shared/dashboard-authoring/outline/outline-dashboard.d.ts +7 -0
- package/dist/types/shared/dashboard-authoring/outline/outline-filters.d.ts +26 -4
- package/dist/types/shared/dashboard-authoring/semantic-auto-join-card.d.ts +22 -0
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@ export declare function useCard(cardId: string): {
|
|
|
21
21
|
resolvedPrimaryDateField: import('../types/semantic-runtime-types.js').ResolvedPrimaryDateField | undefined;
|
|
22
22
|
effectiveCardConfig: import('../types/index.js').CardConfig | undefined;
|
|
23
23
|
isCurrentQueryResult: boolean;
|
|
24
|
+
filterReach: import('../../shared/analytics-protocol/index.js').SemaphorFilterReachEntry[];
|
|
24
25
|
};
|
|
25
26
|
export declare function useDashboardCard(card: TCard): {
|
|
26
27
|
isPending: boolean;
|
|
@@ -42,4 +43,5 @@ export declare function useDashboardCard(card: TCard): {
|
|
|
42
43
|
resolvedPrimaryDateField: import('../types/semantic-runtime-types.js').ResolvedPrimaryDateField | undefined;
|
|
43
44
|
effectiveCardConfig: import('../types/index.js').CardConfig | undefined;
|
|
44
45
|
isCurrentQueryResult: boolean;
|
|
46
|
+
filterReach: import('../../shared/analytics-protocol/index.js').SemaphorFilterReachEntry[];
|
|
45
47
|
};
|
|
@@ -31,4 +31,4 @@ export declare function matrixDeliveryOptions(allowDownload?: boolean, content?:
|
|
|
31
31
|
formats: ("csv" | "xlsx" | "pdf" | "png")[];
|
|
32
32
|
};
|
|
33
33
|
/** Matrix delivery requires an effective capture, never resident cells. */
|
|
34
|
-
export declare function resolveMatrixExportEngine(card: TCard | null | undefined, hasContext: boolean): "
|
|
34
|
+
export declare function resolveMatrixExportEngine(card: TCard | null | undefined, hasContext: boolean): "unavailable" | "window" | "ordinary";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MatrixAxis, MatrixAxisPage, MatrixCellBlock, MatrixCoordinate, MatrixFailure, MatrixPageRequest, MatrixPath, MatrixPresentation, MatrixSpec, MatrixViewState, MatrixWindow, MatrixIndexedWindowOutcome, MatrixWindowRequest, OperationTemporalState, SemaphorScalarValue } from '../../shared/analytics-protocol/index.js';
|
|
1
|
+
import { MatrixAxis, MatrixAxisPage, MatrixCellBlock, MatrixCoordinate, MatrixFailure, MatrixPageRequest, MatrixPath, MatrixPresentation, MatrixSpec, MatrixViewState, MatrixWindow, MatrixIndexedWindowOutcome, MatrixWindowRequest, OperationTemporalState, SemaphorScalarValue, SemaphorFilterReachEntry } from '../../shared/analytics-protocol/index.js';
|
|
2
2
|
export type MatrixRuntimeError = {
|
|
3
3
|
failure: MatrixFailure;
|
|
4
4
|
retryKey: string | null;
|
|
@@ -124,6 +124,12 @@ export type MatrixDataset = {
|
|
|
124
124
|
* or seeded dataset continues on the same instant.
|
|
125
125
|
*/
|
|
126
126
|
temporalState?: OperationTemporalState;
|
|
127
|
+
/**
|
|
128
|
+
* The per-filter report its latest window returned (relationship filter
|
|
129
|
+
* reach RF-D13): a restored dataset shows rows without running a window, so
|
|
130
|
+
* its filter info reads the report saved with them (ledger R-03).
|
|
131
|
+
*/
|
|
132
|
+
filterReach?: readonly SemaphorFilterReachEntry[];
|
|
127
133
|
};
|
|
128
134
|
/** What a mounted runtime exposes to History. */
|
|
129
135
|
export type MatrixLiveView = {
|
|
@@ -208,6 +214,8 @@ export type MatrixWindowExecutor = (input: {
|
|
|
208
214
|
/** A window outcome and the operation state the server ran it on. */
|
|
209
215
|
export type MatrixWindowExecution = MatrixIndexedWindowOutcome & {
|
|
210
216
|
temporalState?: OperationTemporalState;
|
|
217
|
+
/** The per-filter report for this window, as `/api/v1/query` returns it for other cards. */
|
|
218
|
+
filterReach?: SemaphorFilterReachEntry[];
|
|
211
219
|
};
|
|
212
220
|
export type MatrixRuntimeInput = {
|
|
213
221
|
spec: MatrixSpec;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { SemaphorFilterReachEntry, MatrixAxis, MatrixCoordinate, MatrixPath, MatrixSort, MatrixViewState } from '../../shared/analytics-protocol/index.js';
|
|
1
2
|
import { QueryClient } from '@tanstack/react-query';
|
|
2
|
-
import { MatrixAxis, MatrixCoordinate, MatrixPath, MatrixSort, MatrixViewState } from '../../shared/analytics-protocol/index.js';
|
|
3
3
|
import { MatrixCellAddress, MatrixCellState, MatrixDatasetRetention, MatrixRuntimeInput, MatrixRuntimeSnapshot, MatrixViewport, MatrixVisibleCoverage, MatrixWindowExecutor } from './matrix-runtime-types.js';
|
|
4
4
|
/** Owns acquisition, errors, generation fencing and retention for exactly one card. */
|
|
5
5
|
export declare class MatrixRuntimeController {
|
|
@@ -26,6 +26,8 @@ export declare class MatrixRuntimeController {
|
|
|
26
26
|
* every page and expansion sends it, so they all run on one instant.
|
|
27
27
|
*/
|
|
28
28
|
private temporalState?;
|
|
29
|
+
/** The latest window's per-filter report (relationship filter reach RF-D13). */
|
|
30
|
+
private filterReach;
|
|
29
31
|
private error?;
|
|
30
32
|
private notice?;
|
|
31
33
|
private blockingFailures;
|
|
@@ -73,6 +75,8 @@ export declare class MatrixRuntimeController {
|
|
|
73
75
|
* Value, null and empty cells are complete; unloaded and loading cells, axis
|
|
74
76
|
* pages still loading, and queued or active work are not.
|
|
75
77
|
*/
|
|
78
|
+
/** Which filters the latest window's source applied, and why not, as the server reported it. */
|
|
79
|
+
readFilterReach: () => SemaphorFilterReachEntry[];
|
|
76
80
|
readVisibleCoverage: () => MatrixVisibleCoverage;
|
|
77
81
|
/** Used by explicit refresh/retry integrations; latest-issued response wins. */
|
|
78
82
|
refetchCell: (coordinate: MatrixCoordinate) => void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TFilterValue } from '../../components/surfboard/filter/types.js';
|
|
2
2
|
import { NormalizedFilterDashboardInput, ResolvedDashboardInput, TCard } from '../types/common-types.js';
|
|
3
|
-
import { DashboardFilterLogicalValueField,
|
|
3
|
+
import { DashboardFilterLogicalValueField, DashboardFilterFieldTarget, DashboardFilterTargetField, DashboardFilterTargetSource, buildDashboardCardSourceIndex } from '../../shared/dashboard-authoring/index.js';
|
|
4
|
+
import { SemaphorRelationshipRoute, SemaphorSkippedConstraintReason } from '../../shared/analytics-protocol/index.js';
|
|
4
5
|
import { Field } from '../types/explorer-types.js';
|
|
5
6
|
export type DashboardFilterMappingSkipReason = 'outsideScope' | 'noSelection' | 'explicitlyExcluded' | 'notApplicable';
|
|
6
7
|
export type DashboardFilterMappingBlockReason = 'ambiguousAutomaticTarget' | 'staleBinding' | 'invalidSelection' | 'incompatibleValueType' | 'unsupportedTarget';
|
|
@@ -35,7 +36,7 @@ export type DashboardFilterMappingResolution = {
|
|
|
35
36
|
* use, so the server resolves both to the same table alias. Pass the card's
|
|
36
37
|
* grounded executable source when validation returned one.
|
|
37
38
|
*/
|
|
38
|
-
export declare function explorerFieldFromMappingTarget(target:
|
|
39
|
+
export declare function explorerFieldFromMappingTarget(target: DashboardFilterFieldTarget, source?: DashboardFilterTargetField['source']): Field;
|
|
39
40
|
/** Date and datetime are interchangeable; every other type must match exactly. */
|
|
40
41
|
export declare function dashboardFilterDataTypesAreCompatible(sourceType: string, targetType: DashboardFilterTargetField['dataType']): boolean;
|
|
41
42
|
/**
|
|
@@ -47,13 +48,7 @@ export declare function automaticTargetCandidates(params: {
|
|
|
47
48
|
valueField: DashboardFilterLogicalValueField;
|
|
48
49
|
valueSources: DashboardFilterTargetSource[];
|
|
49
50
|
sourceIndex: ReturnType<typeof buildDashboardCardSourceIndex>;
|
|
50
|
-
}):
|
|
51
|
-
/**
|
|
52
|
-
* The source-qualified fields whose values a toolbar filter holds. A filter
|
|
53
|
-
* with an option source has exactly one; an ordinary filter has one per
|
|
54
|
-
* source it is proven to address.
|
|
55
|
-
*/
|
|
56
|
-
export declare function dashboardFilterInputValueFields(input: NormalizedFilterDashboardInput): DashboardFilterTargetField[];
|
|
51
|
+
}): DashboardFilterFieldTarget[];
|
|
57
52
|
export type DashboardFilterTargetValidation = {
|
|
58
53
|
status: 'valid';
|
|
59
54
|
/** The card's own copy of the source the target addresses. */
|
|
@@ -71,7 +66,7 @@ export type DashboardFilterTargetValidation = {
|
|
|
71
66
|
*/
|
|
72
67
|
export declare function validateDashboardFilterTargetForCard(params: {
|
|
73
68
|
sourceIndex: ReturnType<typeof buildDashboardCardSourceIndex>;
|
|
74
|
-
target:
|
|
69
|
+
target: DashboardFilterFieldTarget;
|
|
75
70
|
}): DashboardFilterTargetValidation;
|
|
76
71
|
/**
|
|
77
72
|
* Where a filter input lands on a card: the one decision execution
|
|
@@ -87,7 +82,7 @@ export type DashboardFilterCardTarget = {
|
|
|
87
82
|
} | {
|
|
88
83
|
status: 'bound';
|
|
89
84
|
bindingId: string;
|
|
90
|
-
target:
|
|
85
|
+
target: DashboardFilterFieldTarget;
|
|
91
86
|
validation: Extract<DashboardFilterTargetValidation, {
|
|
92
87
|
status: 'valid';
|
|
93
88
|
}>;
|
|
@@ -103,7 +98,7 @@ export type DashboardFilterCardTarget = {
|
|
|
103
98
|
status: 'sql';
|
|
104
99
|
} | {
|
|
105
100
|
status: 'automatic';
|
|
106
|
-
target:
|
|
101
|
+
target: DashboardFilterFieldTarget;
|
|
107
102
|
}
|
|
108
103
|
/**
|
|
109
104
|
* The card's data takes the filter's field (the one applicability rule) but
|
|
@@ -113,6 +108,22 @@ export type DashboardFilterCardTarget = {
|
|
|
113
108
|
*/
|
|
114
109
|
| {
|
|
115
110
|
status: 'passthrough';
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The value's dataset is one the card's query doesn't use, in the card's
|
|
114
|
+
* semantic domain: the value is sent as it is and the server decides,
|
|
115
|
+
* through the domain's relationships, whether and how it reaches the card
|
|
116
|
+
* (relationship filter reach row 7r). The browser loads no relationships.
|
|
117
|
+
* With `route`, the author chose the relationships (a mapping `relationship`
|
|
118
|
+
* target, RF-D10): the value carries their ids and the server resolves
|
|
119
|
+
* exactly them or blocks the card.
|
|
120
|
+
*/
|
|
121
|
+
| {
|
|
122
|
+
status: 'relationship';
|
|
123
|
+
route?: {
|
|
124
|
+
bindingId: string;
|
|
125
|
+
relationshipIds: string[];
|
|
126
|
+
};
|
|
116
127
|
} | {
|
|
117
128
|
status: 'ambiguous';
|
|
118
129
|
} | {
|
|
@@ -134,7 +145,56 @@ export type DashboardFilterCardReach =
|
|
|
134
145
|
/** More than one field of the card could take it: the card blocks until it is mapped. */
|
|
135
146
|
| 'ambiguous'
|
|
136
147
|
/** The mapping binds a target the card can't run or no longer has: the card blocks until it is mapped again. */
|
|
137
|
-
| 'blocked'
|
|
148
|
+
| 'blocked'
|
|
149
|
+
/**
|
|
150
|
+
* The server decides when the card runs, through the domain's
|
|
151
|
+
* relationships: it may apply the value or skip it with a reason. A reader
|
|
152
|
+
* never counts it as reached.
|
|
153
|
+
*/
|
|
154
|
+
| 'relationship'
|
|
155
|
+
/** A server-side resolver confirmed the route the card will apply (RF-D15). */
|
|
156
|
+
| 'relationshipApplied' | 'notApplicable';
|
|
157
|
+
/** How a filter reaches a card, with the route or the reason a resolver gave (RF-D15). */
|
|
158
|
+
export type DashboardFilterCardReachDetail = {
|
|
159
|
+
reach: DashboardFilterCardReach;
|
|
160
|
+
/** With 'relationshipApplied'. */
|
|
161
|
+
route?: SemaphorRelationshipRoute;
|
|
162
|
+
/** With 'notApplicable' from a resolver. */
|
|
163
|
+
reason?: SemaphorSkippedConstraintReason;
|
|
164
|
+
/** With reason 'relationship_ambiguous'. */
|
|
165
|
+
candidates?: SemaphorRelationshipRoute[];
|
|
166
|
+
/** With 'blocked' from a resolver. */
|
|
167
|
+
message?: string;
|
|
168
|
+
/**
|
|
169
|
+
* With 'automatic' from a resolver: a card the target decision sends to the
|
|
170
|
+
* server to place applies the value on data its query already uses, so no
|
|
171
|
+
* route is needed (ledger R-05).
|
|
172
|
+
*/
|
|
173
|
+
kept?: true;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Supplied by semaphor-app to server-side readers (RF-D15). Synchronous: the
|
|
177
|
+
* app preloads each card's domain. In the browser readers have none and
|
|
178
|
+
* report `relationship` unresolved.
|
|
179
|
+
*/
|
|
180
|
+
export type DashboardRelationshipReachResolver = (query: {
|
|
181
|
+
card: TCard;
|
|
182
|
+
value: TFilterValue;
|
|
183
|
+
}) => {
|
|
184
|
+
status: 'applied';
|
|
185
|
+
route: SemaphorRelationshipRoute;
|
|
186
|
+
}
|
|
187
|
+
/** The card's query already uses the value's dataset: it applies as any filter. */
|
|
188
|
+
| {
|
|
189
|
+
status: 'kept';
|
|
190
|
+
} | {
|
|
191
|
+
status: 'skipped';
|
|
192
|
+
reason: SemaphorSkippedConstraintReason;
|
|
193
|
+
candidates?: SemaphorRelationshipRoute[];
|
|
194
|
+
} | {
|
|
195
|
+
status: 'blocked';
|
|
196
|
+
message: string;
|
|
197
|
+
};
|
|
138
198
|
/**
|
|
139
199
|
* Whether a filter in scope reaches a card, read without a value, from the
|
|
140
200
|
* decision execution makes (`decideDashboardFilterCardTarget`). The dashboard
|
|
@@ -142,6 +202,16 @@ export type DashboardFilterCardReach =
|
|
|
142
202
|
* (MCP dashboard editing SPEC 3.6, 5.4).
|
|
143
203
|
*/
|
|
144
204
|
export declare function describeDashboardFilterCardReach(input: NormalizedFilterDashboardInput, card: TCard): DashboardFilterCardReach;
|
|
205
|
+
/**
|
|
206
|
+
* `describeDashboardFilterCardReach` with the route or reason. With a
|
|
207
|
+
* resolver (server-side readers, RF-D15) a `relationship` card is resolved
|
|
208
|
+
* the way the card query resolves it: applied with its route, not applicable
|
|
209
|
+
* with the reason, or blocked. The value is the filter's own field, as the
|
|
210
|
+
* card would send it; no policy step depends on the operator.
|
|
211
|
+
*/
|
|
212
|
+
export declare function describeDashboardFilterCardReachDetail(input: NormalizedFilterDashboardInput, card: TCard, options?: {
|
|
213
|
+
relationshipReach?: DashboardRelationshipReachResolver;
|
|
214
|
+
}): DashboardFilterCardReachDetail;
|
|
145
215
|
export declare function resolveDashboardFilterMappings({ card, inputs, resolvedInputs, activeFilterValues, shouldApplyDashboardFilters, }: {
|
|
146
216
|
card: TCard;
|
|
147
217
|
inputs: NormalizedFilterDashboardInput[];
|
|
@@ -107,6 +107,12 @@ export type DashboardStore = {
|
|
|
107
107
|
* on load, on entering or leaving edit mode, and when an editable size is chosen.
|
|
108
108
|
*/
|
|
109
109
|
layoutPreviewBreakpoint: Breakpoint | null;
|
|
110
|
+
/**
|
|
111
|
+
* Whether the screen-size bar is open (responsive layouts RL-D21). Closed by
|
|
112
|
+
* default: the editor edits Desktop and the bar appears only when someone
|
|
113
|
+
* opens it. Closed on load and on entering or leaving edit mode.
|
|
114
|
+
*/
|
|
115
|
+
screenSizesOpen: boolean;
|
|
110
116
|
theme?: 'light' | 'dark' | 'system';
|
|
111
117
|
themeStyle?: StyleProps;
|
|
112
118
|
filteringCards?: TCard[];
|
|
@@ -357,6 +363,12 @@ type Actions = {
|
|
|
357
363
|
editSheetLayout: (sheetId: string, breakpoint: GridEditBreakpoint, items: LayoutItem[]) => void;
|
|
358
364
|
/** Shows a screen size look-only, or ends the preview with null (RL-D19). */
|
|
359
365
|
setLayoutPreviewBreakpoint: (breakpoint: Breakpoint | null) => void;
|
|
366
|
+
/**
|
|
367
|
+
* Opens or closes the screen-size bar (RL-D21). Opening in view mode starts a
|
|
368
|
+
* look-only preview at the size shown now; closing ends any preview and
|
|
369
|
+
* returns the editor to Desktop.
|
|
370
|
+
*/
|
|
371
|
+
setScreenSizesOpen: (open: boolean) => void;
|
|
360
372
|
/** The screen size the editor edits: Desktop, Tablet or Phone (RL-D11). */
|
|
361
373
|
setLayoutEditBreakpoint: (breakpoint: EditableBreakpoint) => void;
|
|
362
374
|
/** "Back to automatic" for a customized Tablet or Phone layout, through the layout engine (`reset_to_automatic`). */
|
|
@@ -17,6 +17,33 @@ export type AppliedConstraintField = {
|
|
|
17
17
|
label?: string;
|
|
18
18
|
qualifiedName?: string;
|
|
19
19
|
};
|
|
20
|
+
/** To-one only with key proof (relationship filter reach RF-D12); anything else is to-many. */
|
|
21
|
+
export type SemaphorRelationshipDirection = 'to_one' | 'to_many';
|
|
22
|
+
/**
|
|
23
|
+
* The route a filter value took to a card through the domain's modeled
|
|
24
|
+
* relationships (relationship filter reach). Applied as "keep the card's rows
|
|
25
|
+
* that have at least one matching related row", so no row repeats.
|
|
26
|
+
*/
|
|
27
|
+
export type SemaphorRelationshipRoute = {
|
|
28
|
+
/** Ordered from the base dataset to the value's dataset; non-empty, no repeats. */
|
|
29
|
+
relationshipIds: string[];
|
|
30
|
+
/** The card's dataset the route starts from, for wording ("Projects with ..."). */
|
|
31
|
+
base?: {
|
|
32
|
+
name: string;
|
|
33
|
+
label?: string;
|
|
34
|
+
};
|
|
35
|
+
/** The datasets after the base, in order, for wording ("through Project"). */
|
|
36
|
+
datasets: Array<{
|
|
37
|
+
name: string;
|
|
38
|
+
label?: string;
|
|
39
|
+
}>;
|
|
40
|
+
direction: SemaphorRelationshipDirection;
|
|
41
|
+
/** For a to-many route: the dataset its first to-many step reaches (the copy's "matching {D}"). */
|
|
42
|
+
matchingDataset?: {
|
|
43
|
+
name: string;
|
|
44
|
+
label?: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
20
47
|
export type AppliedFilterCondition = {
|
|
21
48
|
/** The filter the condition came from: a dashboard input, a request filter, a time window. */
|
|
22
49
|
filterId: string;
|
|
@@ -41,6 +68,8 @@ export type AppliedFilterCondition = {
|
|
|
41
68
|
* Absent when it applied to the whole answer.
|
|
42
69
|
*/
|
|
43
70
|
measures?: string[];
|
|
71
|
+
/** The condition reached the card through these relationships. */
|
|
72
|
+
through?: SemaphorRelationshipRoute;
|
|
44
73
|
};
|
|
45
74
|
export type SemaphorAppliedConstraint = ({
|
|
46
75
|
kind: 'filter';
|
|
@@ -61,7 +90,13 @@ export type SemaphorAppliedConstraint = ({
|
|
|
61
90
|
grain?: MetricComparisonWindowGrain;
|
|
62
91
|
};
|
|
63
92
|
/** Why a condition was left out of the executed query. */
|
|
64
|
-
export type SemaphorSkippedConstraintReason = 'dataset_not_reachable' | 'field_not_resolvable' | 'missing_metadata' | 'unsupported_calculated_filter'
|
|
93
|
+
export type SemaphorSkippedConstraintReason = 'dataset_not_reachable' | 'field_not_resolvable' | 'missing_metadata' | 'unsupported_calculated_filter'
|
|
94
|
+
/** The relationships connect, but this card can't take the value through them. */
|
|
95
|
+
| 'relationship_unsupported'
|
|
96
|
+
/** No active modeled relationship connects the value's dataset to the card. */
|
|
97
|
+
| 'relationship_missing'
|
|
98
|
+
/** More than one equally preferred route connects them; the author chooses one. */
|
|
99
|
+
| 'relationship_ambiguous';
|
|
65
100
|
export type SemaphorSkippedConstraint = {
|
|
66
101
|
filterId?: string;
|
|
67
102
|
field?: AppliedConstraintField;
|
|
@@ -72,3 +107,24 @@ export type SemaphorQueryConstraints = {
|
|
|
72
107
|
applied: SemaphorAppliedConstraint[];
|
|
73
108
|
skipped: SemaphorSkippedConstraint[];
|
|
74
109
|
};
|
|
110
|
+
/**
|
|
111
|
+
* Per filter, whether a card query applied it and why not (relationship
|
|
112
|
+
* filter reach RF-D22): built by the server from its one per-card
|
|
113
|
+
* resolution, keyed by the filter's id, never from the deduped evidence.
|
|
114
|
+
*/
|
|
115
|
+
export type SemaphorFilterReachEntry = {
|
|
116
|
+
filterId: string;
|
|
117
|
+
status: 'applied';
|
|
118
|
+
through?: SemaphorRelationshipRoute;
|
|
119
|
+
} | {
|
|
120
|
+
filterId: string;
|
|
121
|
+
status: 'skipped';
|
|
122
|
+
reason: SemaphorSkippedConstraintReason;
|
|
123
|
+
} | {
|
|
124
|
+
filterId: string;
|
|
125
|
+
status: 'blocked';
|
|
126
|
+
message: string;
|
|
127
|
+
};
|
|
128
|
+
export declare function readRelationshipRoute(value: unknown): SemaphorRelationshipRoute | undefined;
|
|
129
|
+
/** Reads `filterReach` from a raw `/api/v1/query` response body; [] when absent or malformed. */
|
|
130
|
+
export declare function readFilterReach(responseBody: unknown): SemaphorFilterReachEntry[];
|
|
@@ -247,14 +247,14 @@ export declare const assistantContextSchema: z.ZodEffects<z.ZodObject<{
|
|
|
247
247
|
kind: "set";
|
|
248
248
|
text: string;
|
|
249
249
|
fingerprint: string;
|
|
250
|
-
omittedValues?: number | undefined;
|
|
251
250
|
notApplied?: "opened_from_another_dashboard" | undefined;
|
|
251
|
+
omittedValues?: number | undefined;
|
|
252
252
|
}, {
|
|
253
253
|
kind: "set";
|
|
254
254
|
text: string;
|
|
255
255
|
fingerprint: string;
|
|
256
|
-
omittedValues?: number | undefined;
|
|
257
256
|
notApplied?: "opened_from_another_dashboard" | undefined;
|
|
257
|
+
omittedValues?: number | undefined;
|
|
258
258
|
}>, z.ZodObject<{
|
|
259
259
|
kind: z.ZodLiteral<"varies">;
|
|
260
260
|
}, "strict", z.ZodTypeAny, {
|
|
@@ -268,8 +268,8 @@ export declare const assistantContextSchema: z.ZodEffects<z.ZodObject<{
|
|
|
268
268
|
kind: "set";
|
|
269
269
|
text: string;
|
|
270
270
|
fingerprint: string;
|
|
271
|
-
omittedValues?: number | undefined;
|
|
272
271
|
notApplied?: "opened_from_another_dashboard" | undefined;
|
|
272
|
+
omittedValues?: number | undefined;
|
|
273
273
|
} | {
|
|
274
274
|
kind: "varies";
|
|
275
275
|
};
|
|
@@ -281,8 +281,8 @@ export declare const assistantContextSchema: z.ZodEffects<z.ZodObject<{
|
|
|
281
281
|
kind: "set";
|
|
282
282
|
text: string;
|
|
283
283
|
fingerprint: string;
|
|
284
|
-
omittedValues?: number | undefined;
|
|
285
284
|
notApplied?: "opened_from_another_dashboard" | undefined;
|
|
285
|
+
omittedValues?: number | undefined;
|
|
286
286
|
} | {
|
|
287
287
|
kind: "varies";
|
|
288
288
|
};
|
|
@@ -610,8 +610,8 @@ export declare const assistantContextSchema: z.ZodEffects<z.ZodObject<{
|
|
|
610
610
|
kind: "set";
|
|
611
611
|
text: string;
|
|
612
612
|
fingerprint: string;
|
|
613
|
-
omittedValues?: number | undefined;
|
|
614
613
|
notApplied?: "opened_from_another_dashboard" | undefined;
|
|
614
|
+
omittedValues?: number | undefined;
|
|
615
615
|
} | {
|
|
616
616
|
kind: "varies";
|
|
617
617
|
};
|
|
@@ -702,8 +702,8 @@ export declare const assistantContextSchema: z.ZodEffects<z.ZodObject<{
|
|
|
702
702
|
kind: "set";
|
|
703
703
|
text: string;
|
|
704
704
|
fingerprint: string;
|
|
705
|
-
omittedValues?: number | undefined;
|
|
706
705
|
notApplied?: "opened_from_another_dashboard" | undefined;
|
|
706
|
+
omittedValues?: number | undefined;
|
|
707
707
|
} | {
|
|
708
708
|
kind: "varies";
|
|
709
709
|
};
|
|
@@ -794,8 +794,8 @@ export declare const assistantContextSchema: z.ZodEffects<z.ZodObject<{
|
|
|
794
794
|
kind: "set";
|
|
795
795
|
text: string;
|
|
796
796
|
fingerprint: string;
|
|
797
|
-
omittedValues?: number | undefined;
|
|
798
797
|
notApplied?: "opened_from_another_dashboard" | undefined;
|
|
798
|
+
omittedValues?: number | undefined;
|
|
799
799
|
} | {
|
|
800
800
|
kind: "varies";
|
|
801
801
|
};
|
|
@@ -886,8 +886,8 @@ export declare const assistantContextSchema: z.ZodEffects<z.ZodObject<{
|
|
|
886
886
|
kind: "set";
|
|
887
887
|
text: string;
|
|
888
888
|
fingerprint: string;
|
|
889
|
-
omittedValues?: number | undefined;
|
|
890
889
|
notApplied?: "opened_from_another_dashboard" | undefined;
|
|
890
|
+
omittedValues?: number | undefined;
|
|
891
891
|
} | {
|
|
892
892
|
kind: "varies";
|
|
893
893
|
};
|
|
@@ -12,6 +12,8 @@ export type ChangeProblemCode = 'invalid_change' | 'invalid_change_target' | 'co
|
|
|
12
12
|
export type ChangeWarningCode =
|
|
13
13
|
/** In-scope cards the filter doesn't reach. */
|
|
14
14
|
'filter_not_reaching_cards'
|
|
15
|
+
/** In-scope cards on another dataset of the filter's domain: decided when each card runs, through the relationships. */
|
|
16
|
+
| 'filter_reach_through_relationships'
|
|
15
17
|
/** The compiled card stores the window as fixed dates. */
|
|
16
18
|
| 'window_saved_as_fixed_dates'
|
|
17
19
|
/** A type change leaves out fields or preferences. */
|
|
@@ -2,6 +2,7 @@ import { TDashboard } from '../../../lib/types/common-types.js';
|
|
|
2
2
|
import { DataSource, Field } from '../../../lib/types/explorer-types.js';
|
|
3
3
|
import { TChartType } from '../../../lib/charts/types.js';
|
|
4
4
|
import { CalendarContext } from '../../report-runtime-context/index.js';
|
|
5
|
+
import { DashboardRelationshipReachResolver } from '../../../lib/query-context/dashboard-filter-mapping-resolution.js';
|
|
5
6
|
import { DashboardOperation, OperationContext, OperationDescription } from '../operations/apply-dashboard-operations.js';
|
|
6
7
|
import { CardQueryPart } from './card-query-part.js';
|
|
7
8
|
import { FieldRef, MetricCardQuery, RecordsCardQuery } from './dashboard-change.js';
|
|
@@ -59,6 +60,12 @@ export type ChangeServices = {
|
|
|
59
60
|
}): Promise<FieldRef[]>;
|
|
60
61
|
/** A new unique id (a UUID: Matrix ids must be UUIDs, ledger P1-04). */
|
|
61
62
|
newId(): string;
|
|
63
|
+
/**
|
|
64
|
+
* Server side only: resolves relationship reach the way the card query
|
|
65
|
+
* does, with each card's domain preloaded (relationship filter reach
|
|
66
|
+
* RF-D15). Without one, those cards read as decided when they run.
|
|
67
|
+
*/
|
|
68
|
+
relationshipReach?: DashboardRelationshipReachResolver;
|
|
62
69
|
};
|
|
63
70
|
export type ChangeRef = {
|
|
64
71
|
ref: string;
|
|
@@ -3,7 +3,7 @@ import { SelectionField } from '../analytics-protocol/selection-contract.js';
|
|
|
3
3
|
import { DashboardInputScope, TCard } from '../../lib/types/common-types.js';
|
|
4
4
|
import { Field } from '../../lib/types/explorer-types.js';
|
|
5
5
|
import { buildDashboardCardSourceIndex, DashboardCardFilterSourceInventory } from './dashboard-card-source-index.js';
|
|
6
|
-
import {
|
|
6
|
+
import { DashboardFilterFieldTarget } from './dashboard-filter-mapping-types.js';
|
|
7
7
|
/** Which fields a click on this card carries. */
|
|
8
8
|
export type ClickToFilterFieldsRule =
|
|
9
9
|
/** Table: every dimension column on the row. Matrix: the full path. Chart: every dimension of the clicked mark. */
|
|
@@ -31,8 +31,8 @@ export type ClickToFilterCardMapping = {
|
|
|
31
31
|
/** Target card. */
|
|
32
32
|
cardId: string;
|
|
33
33
|
clickedFieldKey: string;
|
|
34
|
-
/**
|
|
35
|
-
target:
|
|
34
|
+
/** A field of the target card: a click applies its value to a field the card executes (ledger R-11). */
|
|
35
|
+
target: DashboardFilterFieldTarget;
|
|
36
36
|
}
|
|
37
37
|
/** "Not applied": this target never receives this source's clicks. */
|
|
38
38
|
| {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { DashboardFilterTarget, DashboardFilterTargetField } from './dashboard-filter-mapping-types.js';
|
|
1
|
+
import { DashboardFilterFieldTarget, DashboardFilterTarget, DashboardFilterTargetField } from './dashboard-filter-mapping-types.js';
|
|
2
2
|
export type DashboardFilterLogicalValueField = Pick<DashboardFilterTargetField, 'name' | 'sourceField'> & {
|
|
3
3
|
dataType: DashboardFilterTargetField['dataType'];
|
|
4
4
|
};
|
|
5
5
|
export type DashboardFilterAutomaticTargetResolution = {
|
|
6
6
|
status: 'matched';
|
|
7
|
-
target:
|
|
7
|
+
target: DashboardFilterFieldTarget;
|
|
8
8
|
} | {
|
|
9
9
|
status: 'ambiguous';
|
|
10
10
|
} | {
|
|
@@ -22,7 +22,7 @@ export declare function dashboardFilterTargetMatchesLogicalValue(target: Dashboa
|
|
|
22
22
|
*/
|
|
23
23
|
export declare function resolveDashboardFilterAutomaticTarget(params: {
|
|
24
24
|
logicalValueField: DashboardFilterLogicalValueField;
|
|
25
|
-
candidates:
|
|
25
|
+
candidates: DashboardFilterFieldTarget[];
|
|
26
26
|
}): DashboardFilterAutomaticTargetResolution;
|
|
27
27
|
/**
|
|
28
28
|
* Reuses an accepted, source-qualified target as the default for later config
|
|
@@ -33,5 +33,5 @@ export declare function resolveDashboardFilterAutomaticTarget(params: {
|
|
|
33
33
|
*/
|
|
34
34
|
export declare function resolveDashboardFilterInheritedTarget(params: {
|
|
35
35
|
logicalValueField: DashboardFilterLogicalValueField;
|
|
36
|
-
acceptedTargets:
|
|
36
|
+
acceptedTargets: DashboardFilterFieldTarget[];
|
|
37
37
|
}): DashboardFilterAutomaticTargetResolution;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { DashboardInput, NormalizedDashboardInput, TCard } from '../../lib/types/common-types.js';
|
|
2
2
|
import { TFilter } from '../../components/surfboard/filter/types.js';
|
|
3
|
-
export type DashboardFilterMappingContractIssueCode = 'invalid_input' | 'both_filter_definitions' | 'missing_filter_definition' | 'orphaned_filter_reference' | 'invalid_filter_reference' | 'duplicate_filter_reference' | 'global_date_reference' | 'unsupported_mapped_scope' | 'invalid_application' | 'duplicate_card_application' | 'unknown_card' | 'invalid_binding_id' | 'unsupported_target' | 'invalid_target_field' | 'unknown_target_data_type' | 'unavailable_card_source'
|
|
3
|
+
export type DashboardFilterMappingContractIssueCode = 'invalid_input' | 'both_filter_definitions' | 'missing_filter_definition' | 'orphaned_filter_reference' | 'invalid_filter_reference' | 'duplicate_filter_reference' | 'global_date_reference' | 'unsupported_mapped_scope' | 'invalid_application' | 'duplicate_card_application' | 'unknown_card' | 'invalid_binding_id' | 'unsupported_target' | 'invalid_target_field' | 'unknown_target_data_type' | 'unavailable_card_source'
|
|
4
|
+
/** A relationship target's ids are empty, not strings, or repeat (RF-D10). */
|
|
5
|
+
| 'invalid_relationship_route' | 'invalid_option_source' | 'invalid_option_dependencies' | 'invalid_option_population';
|
|
4
6
|
export type DashboardFilterMappingContractIssue = {
|
|
5
7
|
code: DashboardFilterMappingContractIssueCode;
|
|
6
8
|
path: string;
|
|
@@ -20,10 +20,36 @@ export type DashboardFilterTargetField = {
|
|
|
20
20
|
/** Catalog-grounded physical column used when it differs from the semantic name. */
|
|
21
21
|
sourceField?: string;
|
|
22
22
|
};
|
|
23
|
-
|
|
23
|
+
/**
|
|
24
|
+
* An author-chosen route to a card through the domain's relationships
|
|
25
|
+
* (relationship filter reach RF-D10), for a filter whose value's dataset the
|
|
26
|
+
* card doesn't use and reaches by more than one equally preferred path. The
|
|
27
|
+
* card sends the value as it is with these ids; the server resolves exactly
|
|
28
|
+
* them, or blocks the card while the value is set (P-1).
|
|
29
|
+
*/
|
|
30
|
+
export type DashboardFilterRelationshipTarget = {
|
|
31
|
+
kind: 'relationship';
|
|
32
|
+
/** The value's field on its own dataset (the filter's own field). */
|
|
33
|
+
field: DashboardFilterTargetField;
|
|
34
|
+
/** Ordered from the card's base dataset to `field.source`'s dataset; non-empty, no repeats. */
|
|
35
|
+
relationshipIds: string[];
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* A field of the card the filter's value applies to directly. Field-only
|
|
39
|
+
* code (card field catalogs, automatic targeting, click-to-filter, compiling
|
|
40
|
+
* a card condition) takes this type, so a new target kind never reaches it
|
|
41
|
+
* unchecked (relationship filter reach hotspot H-05).
|
|
42
|
+
*/
|
|
43
|
+
export type DashboardFilterFieldTarget = {
|
|
24
44
|
kind: 'field';
|
|
25
45
|
field: DashboardFilterTargetField;
|
|
26
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* Every target a filter mapping persists. Code that takes both kinds handles
|
|
49
|
+
* each one explicitly (an exhaustive `switch`), so the compiler names it when
|
|
50
|
+
* a kind is added; both kinds carry `field`, so reading it never proves which.
|
|
51
|
+
*/
|
|
52
|
+
export type DashboardFilterTarget = DashboardFilterFieldTarget | DashboardFilterRelationshipTarget;
|
|
27
53
|
export type DashboardFilterBoundCardApplication = {
|
|
28
54
|
kind: 'bound';
|
|
29
55
|
cardId: string;
|
|
@@ -10,9 +10,18 @@ export declare function isDashboardFilterOperationCompatible(dataType: unknown,
|
|
|
10
10
|
export declare const DASHBOARD_FILTER_OPERATIONS: ReadonlySet<string>;
|
|
11
11
|
export type DashboardFilterScalarType = keyof typeof OPERATIONS_BY_DATA_TYPE;
|
|
12
12
|
/**
|
|
13
|
-
* The values a filter operation takes: how many, and of which scalar type.
|
|
14
13
|
* The one rule for stored filter values, in authored defaults and in saved
|
|
15
|
-
* bookmarks
|
|
14
|
+
* bookmarks: the values a filter operation takes (how many, and of which
|
|
15
|
+
* scalar type), and a date window that runs to now. A dashboard filter's
|
|
16
|
+
* dates never count back from the latest data (relationship filter reach
|
|
17
|
+
* RF-INV-13): the Cards tab previews reach without a value, and a route can't
|
|
18
|
+
* carry a data anchor (P-6, ledger R-15). MCP edits already refuse such a
|
|
19
|
+
* default. Appends a message naming `location` (the stored value) for the
|
|
20
|
+
* first problem.
|
|
16
21
|
*/
|
|
17
|
-
export declare function validateDashboardFilterValues(
|
|
22
|
+
export declare function validateDashboardFilterValues(value: {
|
|
23
|
+
operation: unknown;
|
|
24
|
+
values: readonly unknown[];
|
|
25
|
+
relativeMeta?: unknown;
|
|
26
|
+
}, valueType: DashboardFilterScalarType | undefined, location: string, errors: string[]): void;
|
|
18
27
|
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SemaphorRelationshipRoute, SemaphorSkippedConstraintReason } from '../analytics-protocol/index.js';
|
|
2
|
+
/** "Project" to "Projects", "Category" to "Categories"; a label ending in "s" stays. */
|
|
3
|
+
export declare function pluralDatasetLabel(label: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* P-8 and P-11: "through Project" for a to-one route; "Projects with at least
|
|
6
|
+
* one matching Dashboard" for a to-many route, where Dashboard is the dataset
|
|
7
|
+
* its first to-many step reaches. A route of more than one step names the
|
|
8
|
+
* datasets it passes through, not the filter's own, which it always ends at
|
|
9
|
+
* ("through Crew" for a Company filter; ledger R-21).
|
|
10
|
+
*/
|
|
11
|
+
export declare function describeRelationshipRoute(route: SemaphorRelationshipRoute): string;
|
|
12
|
+
/** P-1: a persisted route the domain no longer has. */
|
|
13
|
+
export declare const RELATIONSHIP_ROUTE_CHANGED_MESSAGE = "The relationship this card used changed; choose it again";
|
|
14
|
+
/** P-2, P-3, P-6, P-7: why a value was not applied to a card. */
|
|
15
|
+
export declare function describeRelationshipSkip(reason: SemaphorSkippedConstraintReason, cardDataset?: {
|
|
16
|
+
name: string;
|
|
17
|
+
label?: string;
|
|
18
|
+
}): string;
|