@cosmicdrift/kumiko-headless 0.235.1 → 0.235.3
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-headless",
|
|
3
|
-
"version": "0.235.
|
|
3
|
+
"version": "0.235.3",
|
|
4
4
|
"description": "Headless UI logic for Kumiko — Dispatcher contract, Form-Controller, View-Model, Nav-Resolver. Plattform- und React-frei; jeder Renderer (renderer, renderer-web, renderer-native, …) komponiert darauf.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cosmicdrift/kumiko-framework": "0.235.
|
|
39
|
+
"@cosmicdrift/kumiko-framework": "0.235.3",
|
|
40
40
|
"temporal-polyfill": "^0.3.2",
|
|
41
41
|
"zod": "^4.4.3"
|
|
42
42
|
},
|
|
@@ -3,7 +3,10 @@ import type {
|
|
|
3
3
|
EntityDefinition,
|
|
4
4
|
EntityListScreenDefinition,
|
|
5
5
|
} from "@cosmicdrift/kumiko-framework/ui-types";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
LIST_ROW_META_COLUMNS,
|
|
8
|
+
LIST_ROW_META_REFERENCES,
|
|
9
|
+
} from "@cosmicdrift/kumiko-framework/ui-types";
|
|
7
10
|
import { computeListViewModel } from "../list";
|
|
8
11
|
|
|
9
12
|
// Minimal EntityDefinition-shape. ui-core's view-model only reads
|
|
@@ -283,15 +286,59 @@ describe("computeListViewModel", () => {
|
|
|
283
286
|
featureName: "tasks",
|
|
284
287
|
});
|
|
285
288
|
|
|
289
|
+
const ref = LIST_ROW_META_REFERENCES[field];
|
|
286
290
|
expect(vm.columns[1]).toEqual({
|
|
287
291
|
field,
|
|
288
292
|
label: `tasks:entity:task:field:${field}`,
|
|
289
|
-
|
|
290
|
-
|
|
293
|
+
...(ref !== undefined
|
|
294
|
+
? {
|
|
295
|
+
type: "reference",
|
|
296
|
+
sortable: false,
|
|
297
|
+
refFeature: ref.refFeature,
|
|
298
|
+
refEntity: ref.refEntity,
|
|
299
|
+
refLabelField: ref.refLabelField,
|
|
300
|
+
}
|
|
301
|
+
: { type: expectedType, sortable: true }),
|
|
291
302
|
});
|
|
292
303
|
}
|
|
293
304
|
});
|
|
294
305
|
|
|
306
|
+
// tenantId carries a GUID in the DB but should render the referenced
|
|
307
|
+
// tenant's display name, like a declared reference field does — not the
|
|
308
|
+
// raw GUID. insertedById stays unchanged: this also pins that the map
|
|
309
|
+
// switches exactly one column, not every row-meta ID column.
|
|
310
|
+
test("tenantId row-meta column resolves as a reference column, insertedById unchanged", () => {
|
|
311
|
+
const vm = computeListViewModel({
|
|
312
|
+
screen: listScreen(["tenantId", "insertedById", "id"]),
|
|
313
|
+
entity: taskEntity,
|
|
314
|
+
rows: [],
|
|
315
|
+
translate,
|
|
316
|
+
featureName: "tasks",
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
expect(vm.columns[0]).toEqual({
|
|
320
|
+
field: "tenantId",
|
|
321
|
+
label: "tasks:entity:task:field:tenantId",
|
|
322
|
+
type: "reference",
|
|
323
|
+
sortable: false,
|
|
324
|
+
refFeature: "tenant",
|
|
325
|
+
refEntity: "tenant",
|
|
326
|
+
refLabelField: "name",
|
|
327
|
+
});
|
|
328
|
+
expect(vm.columns[1]).toEqual({
|
|
329
|
+
field: "insertedById",
|
|
330
|
+
label: "tasks:entity:task:field:insertedById",
|
|
331
|
+
type: "text",
|
|
332
|
+
sortable: true,
|
|
333
|
+
});
|
|
334
|
+
expect(vm.columns[2]).toEqual({
|
|
335
|
+
field: "id",
|
|
336
|
+
label: "tasks:entity:task:field:id",
|
|
337
|
+
type: "text",
|
|
338
|
+
sortable: true,
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
|
|
295
342
|
test("row-meta column: explicit label + renderer are passed through unchanged", () => {
|
|
296
343
|
const fmt = { format: "currency" as const, symbol: "€" };
|
|
297
344
|
const vm = computeListViewModel({
|
package/src/view-model/list.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
} from "@cosmicdrift/kumiko-framework/ui-types";
|
|
6
6
|
import {
|
|
7
7
|
LIST_ROW_META_COLUMNS,
|
|
8
|
+
LIST_ROW_META_REFERENCES,
|
|
8
9
|
normalizeListColumn,
|
|
9
10
|
parseRefTarget,
|
|
10
11
|
} from "@cosmicdrift/kumiko-framework/ui-types";
|
|
@@ -50,17 +51,26 @@ export function computeListViewModel(input: ComputeListViewModelInput): ListView
|
|
|
50
51
|
// a real base-table column that's never a declared entity field, e.g.
|
|
51
52
|
// a SystemAdmin cross-tenant list exposing tenantId. Unlike the
|
|
52
53
|
// derivedFields branch above, these are actual DB columns, so
|
|
53
|
-
// server-side ORDER BY works — sortable stays true
|
|
54
|
+
// server-side ORDER BY works — sortable stays true, except for the
|
|
55
|
+
// ID columns in LIST_ROW_META_REFERENCES (see their reference branch).
|
|
54
56
|
const rowMetaType = LIST_ROW_META_COLUMNS[normalized.field];
|
|
55
57
|
if (rowMetaType !== undefined) {
|
|
58
|
+
const rowMetaRef = LIST_ROW_META_REFERENCES[normalized.field];
|
|
56
59
|
columns.push({
|
|
57
60
|
field: normalized.field,
|
|
58
61
|
label: translate(
|
|
59
62
|
normalized.label ?? fieldLabelKey(featureName, screen.entity, normalized.field),
|
|
60
63
|
),
|
|
61
|
-
type: rowMetaType,
|
|
62
|
-
|
|
64
|
+
type: rowMetaRef !== undefined ? "reference" : rowMetaType,
|
|
65
|
+
// The DB column holds the GUID, not the resolved label — server-side
|
|
66
|
+
// ORDER BY would sort by GUID while the cell shows the name.
|
|
67
|
+
sortable: rowMetaRef === undefined,
|
|
63
68
|
...(normalized.renderer !== undefined && { renderer: normalized.renderer }),
|
|
69
|
+
...(rowMetaRef !== undefined && {
|
|
70
|
+
refEntity: rowMetaRef.refEntity,
|
|
71
|
+
refFeature: rowMetaRef.refFeature,
|
|
72
|
+
refLabelField: rowMetaRef.refLabelField,
|
|
73
|
+
}),
|
|
64
74
|
});
|
|
65
75
|
continue;
|
|
66
76
|
}
|