@ngis/plugin-ui 0.4.0 → 0.4.1
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/index.cjs +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/src/api/analysis.d.ts +38 -1
- package/dist/src/api/crs.d.ts +110 -0
- package/dist/src/api/resources.d.ts +174 -10
- package/dist/src/api/scenes.d.ts +103 -4
- package/dist/src/api/workflows.d.ts +10 -1
- package/dist/src/components/plugin-ui/ChartCanvas.d.ts +3 -0
- package/dist/src/components/plugin-ui/ParamForm.d.ts +67 -5
- package/dist/src/components/plugin-ui/PickerField.d.ts +17 -0
- package/dist/src/components/plugin-ui/RunButton.d.ts +8 -0
- package/dist/src/components/plugin-ui/crs-issue-messages.d.ts +157 -0
- package/dist/src/components/plugin-ui/flow-ports.d.ts +17 -0
- package/dist/src/components/plugin-ui/param-widgets.d.ts +2 -2
- package/dist/src/components/plugin-ui/picker-model.d.ts +49 -0
- package/dist/src/components/plugin-ui/run-data.d.ts +32 -4
- package/dist/src/components/plugin-ui/w2-contracts.d.ts +61 -0
- package/dist/src/components/plugin-ui/w3-contracts.d.ts +16 -1
- package/dist/src/components/resources/CrsPicker/CrsChip.d.ts +60 -0
- package/dist/src/components/resources/CrsPicker/CrsParamControl.d.ts +10 -0
- package/dist/src/components/resources/CrsPicker/CrsPicker.d.ts +41 -0
- package/dist/src/components/resources/CrsPicker/crs-recent.d.ts +40 -0
- package/dist/src/components/resources/CrsPicker/index.d.ts +14 -0
- package/dist/src/components/resources/resource-library-crs.d.ts +117 -0
- package/dist/src/components/ui/dialog.d.ts +25 -0
- package/dist/src/domain/algorithms/flow-field-style.d.ts +68 -0
- package/dist/src/domain/map/types.d.ts +2 -0
- package/dist/src/domain/models/crs.d.ts +187 -0
- package/dist/src/domain/models/dataset-kind.d.ts +256 -0
- package/dist/src/domain/models/flow-field-style.d.ts +32 -0
- package/dist/src/features/gis/components/GisAttributeTable.d.ts +11 -3
- package/dist/src/features/gis/hooks/useDatasetFeatureWindow.d.ts +5 -9
- package/dist/src/features/gis/lib/attributeFilters.d.ts +24 -0
- package/dist/src/sdk/facets/types.d.ts +73 -2
- package/dist/src/sdk/map-api.d.ts +5 -2
- package/dist/src/types/analysis.d.ts +111 -7
- package/dist/src/types/extensions.d.ts +43 -0
- package/dist/src/types/gis.d.ts +1 -1
- package/package.json +6 -37
- package/LICENSE +0 -13
- package/README.md +0 -25
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 29 (F29.1 / F29.4 / F29.5 / F29.7 / F29.9) — the frontend's dataset-kind
|
|
3
|
+
* domain model.
|
|
4
|
+
*
|
|
5
|
+
* **This module is the one place in the client that names a dataset kind.** It is
|
|
6
|
+
* the F25.1 `crs.ts` precedent applied to the second vocabulary this platform
|
|
7
|
+
* spelled seven ways: a dataset's kind was spelled seven different ways, in three
|
|
8
|
+
* casings, derived from four different source fields, and no two of the seven had
|
|
9
|
+
* the same membership. After Stage 29 there is **one** derivation chain — the
|
|
10
|
+
* server's `datasetType` — and `G-KIND` is the rule that nothing outside a
|
|
11
|
+
* registry module branches on a kind id.
|
|
12
|
+
*
|
|
13
|
+
* Every shape below mirrors the frozen fixtures in
|
|
14
|
+
* `src/domain/models/__fixtures__/dataset-kind/`, which are byte-identical copies
|
|
15
|
+
* of `ngis-backend/stages/29-resource-plane/fixtures/` (F29.10 — compare with
|
|
16
|
+
* `diff --strip-trailing-cr`, never an on-disk hash: the two repos normalise line
|
|
17
|
+
* endings differently).
|
|
18
|
+
*
|
|
19
|
+
* ## The three-state rule lives here
|
|
20
|
+
*
|
|
21
|
+
* {@link NgisKindCapabilities} is a `Partial<>` and that is **load-bearing**
|
|
22
|
+
* (F29.4, inheriting F25.8). A flag **absent** from the block means *the server
|
|
23
|
+
* has not said*; `{supported: false, reasonKey}` means *this kind cannot*;
|
|
24
|
+
* `{supported: true, reasonKey: null}` means *it can*. A client that coalesces
|
|
25
|
+
* absent into `false` has re-introduced exactly the defect Stage 26 paid to
|
|
26
|
+
* learn — which is why {@link datasetKindCapability} is the only supported way to
|
|
27
|
+
* read a flag and why it returns `undefined` rather than fabricating a record.
|
|
28
|
+
*
|
|
29
|
+
* @see ngis-backend/stages/29-resource-plane/F29-contract.md — F29.1, F29.4,
|
|
30
|
+
* F29.5, F29.7, F29.9 (frozen names)
|
|
31
|
+
* @see docs/resource_plane_stage/README.md — the frontend plan of record
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* **The one client dataset-kind type (F29.1).** The wire field keeps its shipped
|
|
35
|
+
* name, `datasetType`, and its value is a registered kind id in UPPERCASE
|
|
36
|
+
* `SNAKE_CASE`.
|
|
37
|
+
*
|
|
38
|
+
* **The union is OPEN, and that is the whole point.** `D29-1` makes a kind
|
|
39
|
+
* *registered data*, so a client shipped today must render a kind registered
|
|
40
|
+
* tomorrow. The three named members exist for autocomplete and for the
|
|
41
|
+
* exhaustiveness of *today's* switch statements — they are **not** a membership
|
|
42
|
+
* assertion, and **no test may assert that the set of kinds equals those three**.
|
|
43
|
+
* (Stage 15's `Market.*` sub-namespace lesson, which cost a session on three
|
|
44
|
+
* consecutive waves: a closed-world assertion breaks on every sibling merge.)
|
|
45
|
+
*
|
|
46
|
+
* `null` — not a member of this union — keeps exactly one meaning after F29.3:
|
|
47
|
+
* *no kind resolved* (`status: "NEEDS_KIND"`). `"GENERIC"` is gone from the wire;
|
|
48
|
+
* a non-geo file reports `datasetType: null` with `status: "N/A"`.
|
|
49
|
+
*/
|
|
50
|
+
export type NgisDatasetKind = "VECTOR" | "RASTER" | "FLOW_FIELD" | (string & {});
|
|
51
|
+
/**
|
|
52
|
+
* **The six capability flags, frozen (F29.4).**
|
|
53
|
+
*
|
|
54
|
+
* `renderable` is deliberately **not** a member, and that is not an oversight:
|
|
55
|
+
* `renderable` is a server-computed property of a dataset *row*
|
|
56
|
+
* (`ready && geometryType != null && capabilities.tileable.supported === true`,
|
|
57
|
+
* F29.6), never a declared capability of a *kind*. Stage 28 ships a
|
|
58
|
+
* `capabilities.renderable` on a **symbol template**, an unrelated object that
|
|
59
|
+
* happens to share the field name; keeping `renderable` out of this union is what
|
|
60
|
+
* stops a symbol payload from satisfying a dataset capability block
|
|
61
|
+
* (`S29-V073`).
|
|
62
|
+
*/
|
|
63
|
+
export type NgisCapabilityFlag = "tileable" | "analyzable" | "shareable" | "copyable" | "quotaCountable" | "exportable";
|
|
64
|
+
/** The six flags in the F29.4 order. */
|
|
65
|
+
export declare const NGIS_CAPABILITY_FLAGS: readonly NgisCapabilityFlag[];
|
|
66
|
+
/**
|
|
67
|
+
* One declared capability of a kind (F29.4 / F29.5).
|
|
68
|
+
*
|
|
69
|
+
* **A boolean cannot say why a control is greyed**, which is why this is a record
|
|
70
|
+
* and never a bare boolean. `reasonKey` is an **i18n key the client localises** —
|
|
71
|
+
* the server never sends display text for a capability refusal — and `params`
|
|
72
|
+
* carries its interpolation values. The in-repo precedent is shipped:
|
|
73
|
+
* `ValidationIssue.message_key` / `params_json` and `IssueFix.label_key` /
|
|
74
|
+
* `params_json` (`ngis-protos/geoanalysis.proto:553-572`); `IssueFix.params_json`
|
|
75
|
+
* exists *because* a key without its interpolation values made the gRPC and REST
|
|
76
|
+
* twins of one fixture disagree.
|
|
77
|
+
*/
|
|
78
|
+
export interface NgisCapability {
|
|
79
|
+
supported: boolean;
|
|
80
|
+
/** Required when `supported === false`; **must** be `null` when `true`. */
|
|
81
|
+
reasonKey: string | null;
|
|
82
|
+
/** Interpolation values for `reasonKey`; `{}` when the key takes none. */
|
|
83
|
+
params: Record<string, unknown>;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* A kind's declared capability block (F29.4).
|
|
87
|
+
*
|
|
88
|
+
* **`Partial<>` is load-bearing — there are three states, not two.** An absent
|
|
89
|
+
* flag means *the server has not said*, and it must never render as
|
|
90
|
+
* *this kind cannot*. Read a flag with {@link datasetKindCapability} and nothing
|
|
91
|
+
* else.
|
|
92
|
+
*
|
|
93
|
+
* `{}` is the **empty** block and differs from an absent block: it means *no kind
|
|
94
|
+
* resolved, therefore no declared capabilities* (`fx-ds-0003`, `status:
|
|
95
|
+
* "NEEDS_KIND"`). Every flag is then in its third state.
|
|
96
|
+
*
|
|
97
|
+
* The block describes the **kind**, not the row's readiness. A `NEEDS_CRS` vector
|
|
98
|
+
* is still `tileable: true`; it is `ready: false` that stops it rendering.
|
|
99
|
+
* Conflating the two is how `renderable` came to name three kinds.
|
|
100
|
+
*/
|
|
101
|
+
export type NgisKindCapabilities = Partial<Record<NgisCapabilityFlag, NgisCapability>>;
|
|
102
|
+
/**
|
|
103
|
+
* Read one declared capability — **the only supported way to read a flag.**
|
|
104
|
+
*
|
|
105
|
+
* Returns `undefined` for an absent flag and **never fabricates
|
|
106
|
+
* `{supported: false}`**. That is F29.4's three-state rule enforced in one
|
|
107
|
+
* function so no call site can get it wrong; a caller that wants a boolean must
|
|
108
|
+
* decide, explicitly and at its own site, what *"the server has not said"* means
|
|
109
|
+
* for the control it is drawing.
|
|
110
|
+
*
|
|
111
|
+
* The flag argument is typed {@link NgisCapabilityFlag}, so
|
|
112
|
+
* `datasetKindCapability(caps, "renderable")` is a **compile error**
|
|
113
|
+
* (`S29-V073`).
|
|
114
|
+
*/
|
|
115
|
+
export declare function datasetKindCapability(caps: NgisKindCapabilities | null | undefined, flag: NgisCapabilityFlag): NgisCapability | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* Why a dataset's time axis is or is not known (F29.7, `D29-3` generalised from
|
|
118
|
+
* CRS).
|
|
119
|
+
*
|
|
120
|
+
* There are **four** states, and the fourth is the `temporalExtent` field itself
|
|
121
|
+
* being `null`, which means *the server has not said* (F25.8) — distinct from
|
|
122
|
+
* `NOT_APPLICABLE`, which means *this kind has no time axis*.
|
|
123
|
+
*/
|
|
124
|
+
export type NgisTemporalExtentState = "RESOLVED" | "UNRESOLVABLE" | "NOT_APPLICABLE";
|
|
125
|
+
/**
|
|
126
|
+
* A dataset's temporal extent (F29.7).
|
|
127
|
+
*
|
|
128
|
+
* **Never a bare range.** A defaulted range — epoch-to-now, the file's mtime,
|
|
129
|
+
* anything — is a contract violation, not a fallback (`D29-3`). `fx-ds-0005` is
|
|
130
|
+
* the fixture that proves it: `start` and `end` are `null` **and** `state` says
|
|
131
|
+
* why.
|
|
132
|
+
*
|
|
133
|
+
* What each state renders as (F29.7, frozen because `D29-3` forbids a default):
|
|
134
|
+
*
|
|
135
|
+
* | State | Renders as |
|
|
136
|
+
* |---|---|
|
|
137
|
+
* | the field is `null` | the temporal row is **not rendered at all** |
|
|
138
|
+
* | `NOT_APPLICABLE` | the temporal row is **not rendered at all** |
|
|
139
|
+
* | `UNRESOLVABLE` | the row renders, with the localised `reasonKey` where the range would be — never a dash, never an empty range |
|
|
140
|
+
* | `RESOLVED` | the range |
|
|
141
|
+
*
|
|
142
|
+
* `null` and `NOT_APPLICABLE` render identically **on purpose**: there is nothing
|
|
143
|
+
* useful to say to a user in either case. They stay distinct **on the wire**,
|
|
144
|
+
* because a test must be able to tell them apart and the array stage will need to.
|
|
145
|
+
*/
|
|
146
|
+
export interface NgisTemporalExtent {
|
|
147
|
+
state: NgisTemporalExtentState;
|
|
148
|
+
/** ISO 8601; non-null iff `state === "RESOLVED"`. */
|
|
149
|
+
start: string | null;
|
|
150
|
+
/** ISO 8601; non-null iff `state === "RESOLVED"`. */
|
|
151
|
+
end: string | null;
|
|
152
|
+
/** An i18n key; non-null iff `state === "UNRESOLVABLE"`. */
|
|
153
|
+
reasonKey: string | null;
|
|
154
|
+
params: Record<string, unknown>;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Where a dataset came from (F29.7, `D29-5`).
|
|
158
|
+
*
|
|
159
|
+
* `authority` is `AUTHORITY` or `DERIVED`, never both. A `DERIVED` dataset
|
|
160
|
+
* carries `rebuildableFrom`; an `AUTHORITY` one carries `null` there.
|
|
161
|
+
*
|
|
162
|
+
* `sourceFileId` is **not** unique across datasets: `fx-ds-0005` and `fx-ds-0006`
|
|
163
|
+
* share one. That is `D29-2` — one file, many datasets.
|
|
164
|
+
*/
|
|
165
|
+
export interface NgisDatasetLineage {
|
|
166
|
+
authority: "AUTHORITY" | "DERIVED";
|
|
167
|
+
sourceFileId: string | null;
|
|
168
|
+
derivedFromFileId: string | null;
|
|
169
|
+
producedByTaskId: string | null;
|
|
170
|
+
/** Non-null iff `authority === "DERIVED"`. */
|
|
171
|
+
rebuildableFrom: string | null;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* The array plane's placeholder (F29.7, `D29-S1`).
|
|
175
|
+
*
|
|
176
|
+
* **Deliberately typed `null` and nothing else.** `dimensions` is declared on the
|
|
177
|
+
* wire so the array stage needs no second migration and no second contract
|
|
178
|
+
* freeze, and it is `null` for every kind Stage 29 registers. Typing it as the
|
|
179
|
+
* `null` literal makes *"a session that builds a time slider off it is out of
|
|
180
|
+
* contract"* a compile error rather than a code-review note; widening this alias
|
|
181
|
+
* is the array stage's job and nobody else's.
|
|
182
|
+
*/
|
|
183
|
+
export type NgisDatasetDimensions = null;
|
|
184
|
+
/**
|
|
185
|
+
* **The dataset spine (F29.7), as one nominal shape.**
|
|
186
|
+
*
|
|
187
|
+
* *Recorded extra export, not in F29.9's table — see the S29-14 session note.*
|
|
188
|
+
* It exists for `S29-V073`: `renderable` and `ready` are members of a record that
|
|
189
|
+
* also requires `datasetType`, `status` and `lineage`, so a Stage 28 **symbol
|
|
190
|
+
* template** — which carries `capabilities.renderable` and none of those — cannot
|
|
191
|
+
* resolve against the client's **dataset** `renderable`. Two unrelated objects
|
|
192
|
+
* share one field name; this type and {@link NgisCapabilityFlag}'s exclusion of
|
|
193
|
+
* `renderable` are the two independent guards that keep them apart.
|
|
194
|
+
*
|
|
195
|
+
* `ready` and `renderable` are server-computed and keep their names (F29.6):
|
|
196
|
+
*
|
|
197
|
+
* ```
|
|
198
|
+
* ready = status ∈ kind.readyStates
|
|
199
|
+
* renderable = ready && geometryType != null && capabilities.tileable.supported === true
|
|
200
|
+
* ```
|
|
201
|
+
*
|
|
202
|
+
* Both are optional, and `undefined` ("the server has not said") must never render
|
|
203
|
+
* the same as `false` ("this kind cannot be tiled") — `SceneWorkspaceLayers.tsx`'s
|
|
204
|
+
* `resolveLayerCrs` is the in-repo precedent and its comment states the rule.
|
|
205
|
+
*/
|
|
206
|
+
export interface NgisDatasetSpine {
|
|
207
|
+
/** `null` means *no kind resolved* — the only meaning `null` carries (F29.3). */
|
|
208
|
+
datasetType: NgisDatasetKind | null;
|
|
209
|
+
/**
|
|
210
|
+
* **An OPEN vocabulary (F29.7 R2).** A consumer that does not recognise a
|
|
211
|
+
* status renders the **raw token**, never `UNKNOWN`. The measured hazard is
|
|
212
|
+
* live: `ngis-file`'s `FileService` normalises a status through a whitelist
|
|
213
|
+
* whose default arm is `UNKNOWN`, so a `NEEDS_CRS` dataset already reports as
|
|
214
|
+
* `UNKNOWN` on the library listing — *"we know exactly what is wrong with it"*
|
|
215
|
+
* collapsed into *"we do not know"*, which is the very thing `D29-3` forbids.
|
|
216
|
+
*/
|
|
217
|
+
status: string;
|
|
218
|
+
capabilities?: NgisKindCapabilities;
|
|
219
|
+
temporalExtent?: NgisTemporalExtent | null;
|
|
220
|
+
dimensions?: NgisDatasetDimensions;
|
|
221
|
+
lineage?: NgisDatasetLineage | null;
|
|
222
|
+
ready?: boolean;
|
|
223
|
+
renderable?: boolean;
|
|
224
|
+
}
|
|
225
|
+
/** The minimum an issue must carry for {@link isKindAdaptableIssue} to judge it. */
|
|
226
|
+
export interface NgisIssueCodeCarrier {
|
|
227
|
+
code?: string | null;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* F29.8's rule A1, in one place: is this the **kind** adaptation, or Stage 26's
|
|
231
|
+
* **CRS** one?
|
|
232
|
+
*
|
|
233
|
+
* `"ADAPTABLE"` is the same verdict token for both. **Only the issue code
|
|
234
|
+
* distinguishes them** — a test that asserts only `verdict === "ADAPTABLE"`
|
|
235
|
+
* passes on a CRS adaptation and proves Stage 26's code path, not this stage's.
|
|
236
|
+
*
|
|
237
|
+
* The client never re-classifies a server verdict or severity (`G-U`): this is a
|
|
238
|
+
* predicate over a code the server sent, and nothing more.
|
|
239
|
+
*/
|
|
240
|
+
export declare function isKindAdaptableIssue(issue: NgisIssueCodeCarrier | null | undefined): boolean;
|
|
241
|
+
/**
|
|
242
|
+
* The kind → scene-layer resource-kind projection.
|
|
243
|
+
*
|
|
244
|
+
* *Recorded extra export, not in F29.9's table — see the S29-14 session note.*
|
|
245
|
+
* It is what F29.1 row 6 means by *"S29-14 delegates it to `NgisDatasetKind`"*:
|
|
246
|
+
* `SceneLayerResourceKind` used to be reached by `geometry.includes("raster")`, a
|
|
247
|
+
* substring match on a geometry string, and that is a guess. The spine now
|
|
248
|
+
* carries the answer, and this is the one place the answer is projected onto the
|
|
249
|
+
* two-value vocabulary the scene-layer type table is written in.
|
|
250
|
+
*
|
|
251
|
+
* Returns `null` for a kind that is neither — including an unregistered kind the
|
|
252
|
+
* client has never seen, which is `NgisDatasetKind` being open — so a caller must
|
|
253
|
+
* decide what *"I cannot place this kind"* means rather than being handed
|
|
254
|
+
* `"vector"` by default.
|
|
255
|
+
*/
|
|
256
|
+
export declare function sceneLayerResourceKindOfDatasetKind(kind: NgisDatasetKind | null | undefined): "vector" | "raster" | null;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Canonical, per-scene-layer presentation state for a FLOW_FIELD resource. */
|
|
2
|
+
export interface FlowFieldColorRamp {
|
|
3
|
+
/** A UI hint only. `colors` is the renderer authority. */
|
|
4
|
+
presetId: string;
|
|
5
|
+
/** Low-speed to high-speed colors. */
|
|
6
|
+
colors: string[];
|
|
7
|
+
}
|
|
8
|
+
export type FlowFieldSpeedRange = {
|
|
9
|
+
mode: "data";
|
|
10
|
+
} | {
|
|
11
|
+
mode: "manual";
|
|
12
|
+
min: number;
|
|
13
|
+
max: number;
|
|
14
|
+
};
|
|
15
|
+
export interface FlowFieldStyle {
|
|
16
|
+
renderer: "flow-field";
|
|
17
|
+
styleVersion: 1;
|
|
18
|
+
/** Compatibility-only identity for scenes created before SceneResource links. */
|
|
19
|
+
flowFieldId?: string;
|
|
20
|
+
opacity: number;
|
|
21
|
+
colorRamp: FlowFieldColorRamp;
|
|
22
|
+
speedRange: FlowFieldSpeedRange;
|
|
23
|
+
speedFactor: number;
|
|
24
|
+
particleCount: number;
|
|
25
|
+
lineWidth: number;
|
|
26
|
+
trailLength: number;
|
|
27
|
+
frameDurationMs: number;
|
|
28
|
+
paused: boolean;
|
|
29
|
+
maxParticleAge: number;
|
|
30
|
+
dropRate: number;
|
|
31
|
+
dropRateBump: number;
|
|
32
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DatasetAttributeSelection, type DatasetFeatureRow } from "../../../api/resources";
|
|
1
|
+
import { type DatasetAttributeFilter, type DatasetAttributeSelection, type DatasetFeatureRow } from "../../../api/resources";
|
|
2
2
|
/**
|
|
3
3
|
* **Exported for `@ngis/plugin-ui`'s `<AttributeTable>` (Stage 14 Y4b).** It was
|
|
4
4
|
* file-private while this component had exactly one call site
|
|
@@ -30,20 +30,28 @@ export interface GisAttributeTableProps {
|
|
|
30
30
|
onRunTool: (selection: DatasetAttributeSelection) => Promise<void>;
|
|
31
31
|
/** A selection made with the scene's feature-select tool, keyed by stable row id. */
|
|
32
32
|
mapSelection?: {
|
|
33
|
-
|
|
33
|
+
selection: GisAttributeTableSelectionHighlight;
|
|
34
34
|
/** Attribute values present in the selected vector-tile features. */
|
|
35
35
|
rows?: DatasetFeatureRow[];
|
|
36
|
+
/** Opens this selection in the table's normal “only selected” mode. */
|
|
37
|
+
showSelectedOnly?: boolean;
|
|
36
38
|
serial: number;
|
|
37
39
|
} | null;
|
|
38
40
|
}
|
|
41
|
+
/** Whether a fresh external selection must keep the selected-only view enabled. */
|
|
42
|
+
export declare function isApplyingMapSelectedOnly(mapSelection: GisAttributeTableProps["mapSelection"], appliedSerial: number | null): boolean;
|
|
39
43
|
/** The table's complete selection meaning, forwarded to the map highlight. */
|
|
40
44
|
export type GisAttributeTableSelectionHighlight = {
|
|
41
45
|
featureIds: string[];
|
|
42
46
|
allFeatures?: false;
|
|
47
|
+
selectedCount: number;
|
|
43
48
|
} | {
|
|
44
49
|
featureIds: [];
|
|
45
50
|
allFeatures: true;
|
|
46
51
|
excludedFeatureIds: string[];
|
|
52
|
+
selectedCount: number | null;
|
|
53
|
+
/** The same API filter that defines this all-matching selection. */
|
|
54
|
+
filter?: DatasetAttributeFilter;
|
|
47
55
|
};
|
|
48
56
|
/**
|
|
49
57
|
* Attribute table for the selected vector layer's dataset. Server-driven:
|
|
@@ -53,4 +61,4 @@ export type GisAttributeTableSelectionHighlight = {
|
|
|
53
61
|
* a column picker, a filter builder, and dataset-wide selection keyed by the
|
|
54
62
|
* stable feature `id` (so it spans windows that aren't even loaded).
|
|
55
63
|
*/
|
|
56
|
-
export declare function GisAttributeTable({ fileId,
|
|
64
|
+
export declare function GisAttributeTable({ fileId, active, onHighlight, onSelectionChange, onRunTool, mapSelection, }: GisAttributeTableProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type DatasetAttributeFilter, type DatasetAttributeQueryParams, type DatasetFeatureRow } from "../../../api/resources";
|
|
2
2
|
/** One server-side sort directive (single-column for now). */
|
|
3
3
|
export interface FeatureSort {
|
|
4
4
|
field: string;
|
|
5
5
|
dir: "asc" | "desc";
|
|
6
6
|
}
|
|
7
|
-
/** One server-side filter condition (mirrors the query `where` clause). */
|
|
8
|
-
export interface FeatureFilter {
|
|
9
|
-
field: string;
|
|
10
|
-
op: DatasetAttributeWhereOp;
|
|
11
|
-
value: unknown;
|
|
12
|
-
}
|
|
13
7
|
export interface DatasetFeatureWindowParams {
|
|
14
8
|
fileId: string;
|
|
15
9
|
/** Active sort (null = server default order). */
|
|
16
10
|
sort: FeatureSort | null;
|
|
17
|
-
/**
|
|
18
|
-
|
|
11
|
+
/** Final API FilterSpec, shared with count and selection actions. */
|
|
12
|
+
filter?: DatasetAttributeFilter;
|
|
19
13
|
/** Columns to request (empty = all). `id` is always returned regardless. */
|
|
20
14
|
select: string[];
|
|
15
|
+
/** Enumerated stable ids used by normal attribute queries and pagination. */
|
|
16
|
+
featureIds?: string[];
|
|
21
17
|
enabled?: boolean;
|
|
22
18
|
}
|
|
23
19
|
export interface DatasetFeatureWindow {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { DatasetAttributeFilter, DatasetAttributeWhereOp } from "../../../api/resources";
|
|
2
|
+
import type { HighlightFilterExpression } from "../../../domain/map/types";
|
|
3
|
+
/** UI-only `between` expands to the two comparison operators the API supports. */
|
|
4
|
+
export type AttributeFilterOperator = DatasetAttributeWhereOp | "between";
|
|
5
|
+
export interface AttributeFilterCondition {
|
|
6
|
+
field: string;
|
|
7
|
+
op: AttributeFilterOperator;
|
|
8
|
+
value: unknown;
|
|
9
|
+
}
|
|
10
|
+
/** Escape SQL LIKE metacharacters before surrounding a user keyword with `%`. */
|
|
11
|
+
export declare function escapeLikeKeyword(keyword: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Converts UI filter conditions into the API's supported, AND-combined where
|
|
14
|
+
* clauses. This is the sole FilterSpec used by query, count, and all-matching
|
|
15
|
+
* selection actions.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildDatasetAttributeFilter(conditions: readonly AttributeFilterCondition[]): DatasetAttributeFilter | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Converts the API filter already used for the table query into the equivalent
|
|
20
|
+
* MapLibre predicate for the attribute-selection overlay. `like` arrives here
|
|
21
|
+
* in the frontend's deliberate `%escaped keyword%` form, so it maps to a
|
|
22
|
+
* literal substring match rather than a wildcard expression.
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildAttributeHighlightFilter(filter: DatasetAttributeFilter | undefined): HighlightFilterExpression | undefined;
|
|
@@ -32,7 +32,9 @@
|
|
|
32
32
|
*/
|
|
33
33
|
import type { AnalysisToolSchema } from "../../api/analysis";
|
|
34
34
|
import type { SceneType } from "../../api/scenes";
|
|
35
|
+
import type { NgisCrsRef } from "../../domain/models/crs";
|
|
35
36
|
import type { NgisExecutionValidation, NgisToolUiSchema } from "../../types/analysis";
|
|
37
|
+
import type { NgisResolvedToolDependency } from "../../types/extensions";
|
|
36
38
|
import type { NgisBounds, NgisUnsubscribe } from "../map-api";
|
|
37
39
|
export interface NgisSceneInfo {
|
|
38
40
|
id: string;
|
|
@@ -59,6 +61,18 @@ export interface NgisSceneFacet {
|
|
|
59
61
|
* `"table"` would need `NgisFile.fileType`, i.e. a second
|
|
60
62
|
* `GET /api/files/{fileId}` per resource — an N+1 fan-out for a distinction no
|
|
61
63
|
* v1 consumer needs.
|
|
64
|
+
*
|
|
65
|
+
* **SURVIVES Stage 29 UNCHANGED (F29.1 row 3).** It is the SDK's v1
|
|
66
|
+
* plugin-facing classification, frozen by XD7/F13.6 and enforced by two live
|
|
67
|
+
* gates, and Stage 29 registers **no table dataset model** — so nothing about it
|
|
68
|
+
* moves (F29.2). It is a *projection* of `NgisDatasetKind` onto the coarser
|
|
69
|
+
* vocabulary v1 plugins compile against, never a second spelling of it: its
|
|
70
|
+
* membership is closed because a plugin's `when` expression is, and
|
|
71
|
+
* `NgisDatasetKind` is open because a kind is registered data. Widening this one
|
|
72
|
+
* to match would break every shipped plugin fixture.
|
|
73
|
+
*
|
|
74
|
+
* *(`GENERIC` no longer reaches the classifier — F29.3 removed it from the wire —
|
|
75
|
+
* but the "everything else" arm is unchanged and still catches it.)*
|
|
62
76
|
*/
|
|
63
77
|
export type NgisResourceType = "vector" | "raster" | "table" | "file";
|
|
64
78
|
/**
|
|
@@ -89,6 +103,13 @@ export type NgisResourceType = "vector" | "raster" | "table" | "file";
|
|
|
89
103
|
* against a builtin node's `"Raster"` and `400`s at workflow save. Y6 applies
|
|
90
104
|
* that column at, and **only** at, the `ngis-workflow` boundary. Nowhere else
|
|
91
105
|
* in either repo is Pascal correct.
|
|
106
|
+
*
|
|
107
|
+
* **SURVIVES Stage 29 UNCHANGED (F29.1 row 4).** It is a **tool port** data type
|
|
108
|
+
* (F14.1), not a dataset kind. The two are related by the compatibility matrix
|
|
109
|
+
* and **never by equality**: `table` and `pointcloud` are legal port types that
|
|
110
|
+
* no registered kind emits, and a registered kind the client has never seen binds
|
|
111
|
+
* to a port through the matrix rather than by name. Renaming or merging them
|
|
112
|
+
* would assert an identity that does not hold.
|
|
92
113
|
*/
|
|
93
114
|
export type NgisDataType = "raster" | "vector" | "table" | "pointcloud" | "raster3d" | "file";
|
|
94
115
|
export declare const NGIS_DATA_TYPES: readonly ["raster", "vector", "table", "pointcloud", "raster3d", "file"];
|
|
@@ -130,6 +151,25 @@ export interface NgisResourceSummary {
|
|
|
130
151
|
geometryType: string | null;
|
|
131
152
|
layerCount: number;
|
|
132
153
|
rendered: boolean;
|
|
154
|
+
/**
|
|
155
|
+
* **Stage 25 (F25.1 / F25.9, `S25-V216`).** The dataset's one CRS, or `null`
|
|
156
|
+
* when the server has none for it (`NEEDS_CRS`).
|
|
157
|
+
*
|
|
158
|
+
* It is on the **summary**, not only the detail, and that placement is the
|
|
159
|
+
* point of the row. `ResourceSelect` lists datasets from `resources.list()`
|
|
160
|
+
* and must draw each row's projection state at pick time (F25.5); resolving a
|
|
161
|
+
* ref through `resources.get()` per row is the N+1 XD7 already refused for
|
|
162
|
+
* `resources.types`. Without this field the picker could draw only the
|
|
163
|
+
* *absent* state — which is what S25-22 shipped, with the limit recorded
|
|
164
|
+
* rather than papered over — because a dataset that *has* a projection had
|
|
165
|
+
* nothing to draw a chip from and inventing one is what G-CRS forbids.
|
|
166
|
+
*
|
|
167
|
+
* `null` is a value and not a gap: it is the server saying `NEEDS_CRS`. There
|
|
168
|
+
* is no `undefined` arm — the facet always answers, and a dataset it could not
|
|
169
|
+
* read at all reports `datasetStatus: "N/A"` with `crs: null`, which is the
|
|
170
|
+
* same honest "we cannot say what this is in".
|
|
171
|
+
*/
|
|
172
|
+
crs: NgisCrsRef | null;
|
|
133
173
|
/**
|
|
134
174
|
* Scene layers that render this resource, when the host can supply them.
|
|
135
175
|
*
|
|
@@ -160,7 +200,6 @@ export interface NgisResourceField {
|
|
|
160
200
|
type: string;
|
|
161
201
|
}
|
|
162
202
|
export interface NgisResourceDetail extends NgisResourceSummary {
|
|
163
|
-
srid: number | null;
|
|
164
203
|
/** Vector only; `null` otherwise. */
|
|
165
204
|
featureCount: number | null;
|
|
166
205
|
/** Vector only; `[]` otherwise. */
|
|
@@ -244,7 +283,21 @@ export interface NgisModelValidateRequest {
|
|
|
244
283
|
expectedSceneGeneration?: number;
|
|
245
284
|
outputMode?: "ADD_LAYER" | "UPDATE_RESOURCE";
|
|
246
285
|
targetResourceId?: string;
|
|
247
|
-
|
|
286
|
+
/**
|
|
287
|
+
* **Stage 25 (F25.4, and the `S25-V124` ruling that AMENDS F25.12).**
|
|
288
|
+
*
|
|
289
|
+
* Replaces `targetSrid?: number`. It is an {@link NgisCrsRef} **key** — the
|
|
290
|
+
* string `"EPSG:32650"` or `"custom:<ulid>"` — and never an integer, because
|
|
291
|
+
* an integer cannot name a custom CRS at all and because a bare number is the
|
|
292
|
+
* silent-default spelling G-CRS refuses.
|
|
293
|
+
*
|
|
294
|
+
* `targetSrid` was typed, forwarded to `validate-execution` and set by no
|
|
295
|
+
* component: dead plumbing. This member is the live one — `run-data.ts` fills
|
|
296
|
+
* it from the form's `ngis:outputCrs` parameter and the facade adapter puts it
|
|
297
|
+
* on the wire as `outputCrs` (the REST leg is camelCase here; the proto
|
|
298
|
+
* spelling is `output_crs`).
|
|
299
|
+
*/
|
|
300
|
+
outputCrs?: string;
|
|
248
301
|
}
|
|
249
302
|
export interface NgisModelSearchRequest {
|
|
250
303
|
query?: string;
|
|
@@ -300,6 +353,12 @@ export interface NgisModelsFacet {
|
|
|
300
353
|
/** The one normalized UI schema (F14.2). `null` when the tool or its schema
|
|
301
354
|
* is absent. Scope `models:read`. */
|
|
302
355
|
uiSchema(toolId: string): Promise<NgisToolUiSchema | null>;
|
|
356
|
+
/**
|
|
357
|
+
* Resolves a declared `manifest.toolDependencies[].alias` for this plugin and
|
|
358
|
+
* viewer. The unavailable arm is a normal, renderable result; it never leaks
|
|
359
|
+
* implementation UUIDs into plugin manifests. Scope `models:read`.
|
|
360
|
+
*/
|
|
361
|
+
dependency(alias: string): Promise<NgisResolvedToolDependency>;
|
|
303
362
|
/** REST projection of `ValidateToolExecution`. Returns the response DTO
|
|
304
363
|
* **verbatim**. Scope `models:read`, **not** `models:run` — it runs nothing,
|
|
305
364
|
* and returns only registry facts plus dataset metadata the caller can
|
|
@@ -324,6 +383,18 @@ export interface NgisTaskRunRequest {
|
|
|
324
383
|
expectedSceneGeneration?: number;
|
|
325
384
|
outputMode?: "ADD_LAYER" | "UPDATE_RESOURCE";
|
|
326
385
|
targetResourceId?: string;
|
|
386
|
+
/**
|
|
387
|
+
* **Stage 25 (F25.4).** The output CRS this run computes in and stores its
|
|
388
|
+
* result as — an {@link NgisCrsRef} key, never an integer. Absent means
|
|
389
|
+
* "compute in the primary input's own CRS", which is a real choice and not a
|
|
390
|
+
* default: the server never substitutes one (G-CRS).
|
|
391
|
+
*
|
|
392
|
+
* This is the member that makes exit criterion 6 true. `submitRun` fills it,
|
|
393
|
+
* the tasks facet spreads the request through to the DIRECT source, and
|
|
394
|
+
* `createGisTasksSource` hands it to `startTrackedAnalysisTask`, which puts
|
|
395
|
+
* `outputCrs` in the `POST /api/analysis/tasks` body.
|
|
396
|
+
*/
|
|
397
|
+
outputCrs?: string;
|
|
327
398
|
}
|
|
328
399
|
export interface NgisTaskHandle {
|
|
329
400
|
/** DIRECT: the analysis task id. WORKFLOW: the workflow instance id. */
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
import type { Map as MapLibreMap } from "maplibre-gl";
|
|
39
39
|
import type { SceneLayerHighlight, SceneMapView } from "../domain/map/types";
|
|
40
40
|
import type { GisDrawMode, GisMeasureKind } from "../types/gis";
|
|
41
|
-
import type { WorkspacePanelRegistry } from "
|
|
41
|
+
import type { WorkspacePanelRegistry } from "@ngis/plugin-sdk";
|
|
42
42
|
/** Current facade contract version — bumped when the frozen surface changes.
|
|
43
43
|
* A plugin's `minNgisVersion` (`docs/frontend-map-sdk.md` §3) is
|
|
44
44
|
* checked against this. Pre-1.0: the surface may still grow (additively).
|
|
@@ -73,7 +73,7 @@ import type { WorkspacePanelRegistry } from "./panels";
|
|
|
73
73
|
* semver compare, **not** by the unknown-capability check: `contributes` and
|
|
74
74
|
* `permissions` are top-level manifest siblings, and a 0.3 runtime inspects
|
|
75
75
|
* only `manifest.capabilities`. */
|
|
76
|
-
export declare const NGIS_MAP_API_VERSION = "0.4.
|
|
76
|
+
export declare const NGIS_MAP_API_VERSION = "0.4.1";
|
|
77
77
|
/** A scene layer as the SDK exposes it — a stable projection of the store's
|
|
78
78
|
* `NgisSceneLayer`, so plugins never depend on the store's internal shape. */
|
|
79
79
|
export interface NgisLayerSummary {
|
|
@@ -262,6 +262,9 @@ export interface NgisMapAPIBindings {
|
|
|
262
262
|
/** Raw-map getter for `getMap()`. Usually omitted at construction and wired
|
|
263
263
|
* later via `NgisMapAPIHandle.bindRawMap` (the post-C5 hookup). */
|
|
264
264
|
getRawMap?(): MapLibreMap | null;
|
|
265
|
+
/** Host hook run before direct raw-map camera commands. Keeps host-owned
|
|
266
|
+
* temporary camera controllers from racing this SDK escape hatch. */
|
|
267
|
+
beforeCameraCommand?(map: MapLibreMap): void;
|
|
265
268
|
}
|
|
266
269
|
/**
|
|
267
270
|
* The factory's return value: the public `api` plus the host-side "driver"
|