@ai-matrx/records-ui 0.69.0 → 0.71.0
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/CHANGELOG.md +55 -0
- package/dist/index.cjs +95 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -43
- package/dist/index.d.ts +74 -43
- package/dist/index.js +192 -122
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,60 @@
|
|
|
1
1
|
# Changelog — @ai-matrx/records-ui
|
|
2
2
|
|
|
3
|
+
## 0.71.0
|
|
4
|
+
|
|
5
|
+
**A public form no longer takes the page down when it asks for a choice, a linked record or a
|
|
6
|
+
person.** (lane FIX-10A, from VERIFIER-10 finding F1.)
|
|
7
|
+
|
|
8
|
+
An agent built and published a job-request form for a plumbing company in forty seconds and
|
|
9
|
+
handed over its link. Opened by a signed-out stranger — the only person that link is for — it
|
|
10
|
+
answered **HTTP 500**, on production, with `useRecordsClient was called outside
|
|
11
|
+
<RecordsProvider>` in the console.
|
|
12
|
+
|
|
13
|
+
The public arm of `FormRunner` is deliberately the arm that mounts **no store client**: the
|
|
14
|
+
server resolved the Fields through `custom.form_public`, and the browser on that page holds no
|
|
15
|
+
key, knows no organization and may not read a row. `useOptionalRecordsClient` exists in
|
|
16
|
+
`@ai-matrx/records` for exactly that screen. But three of the editors `FieldControl` can draw
|
|
17
|
+
asked for the client with `useRecordsClient`, which throws by design — so **any** public form
|
|
18
|
+
carrying a drop-down, a relation or a person question died, whatever it was about.
|
|
19
|
+
|
|
20
|
+
* **`OptionControl`, `RelationPicker` and `PersonPicker` now take the optional client** and,
|
|
21
|
+
with none mounted, are **absent and honest** instead of fatal. A choice question takes the
|
|
22
|
+
answer as text and says why the list cannot be read on a page answered without an account; a
|
|
23
|
+
relation question says it cannot be answered here and to leave it blank; a person question
|
|
24
|
+
already had that sentence and now reaches it instead of throwing above it.
|
|
25
|
+
* **The guard** — `src/a-public-form-needs-no-store-client.test.tsx` — walks `FIELD_KINDS`, the
|
|
26
|
+
store's own closed list of the nineteen kinds a Field can be, and renders the public arm with
|
|
27
|
+
a question of every one of them and no provider of any sort above it. Red on the bytes before
|
|
28
|
+
this release (4 of 19), green on these. A twentieth kind whose editor reaches for the store
|
|
29
|
+
turns it red the day it is added, not the day a stranger opens a link.
|
|
30
|
+
|
|
31
|
+
## 0.70.0
|
|
32
|
+
|
|
33
|
+
**The bar that said four now opens four.** (lane DRILL.)
|
|
34
|
+
|
|
35
|
+
* **`TablePage` takes a `filter`** — the store's one `RecordFilter` — and hands it to the grid
|
|
36
|
+
AND the board, so switching layout after a drill-through does not quietly widen back to the
|
|
37
|
+
whole table. It is a question for this visit, like `activeView` and `activeGroupField`, and
|
|
38
|
+
is never written onto the saved view. `Grid` and `ViewSwitcher` (and `useViewRecords`) take
|
|
39
|
+
it too; the narrowing happens in the STORE, never in the browser, because this screen holds
|
|
40
|
+
one page and a browser-side filter would drop every match on page two.
|
|
41
|
+
* **`cameFromLine` says the narrow thing, and means it.** TAILS-6 shipped *"This is every
|
|
42
|
+
record grouped into the same columns the chart used — not only the ones that number
|
|
43
|
+
counted"*, which was TRUE and useless: no door took a filter. It now reads *"These are only
|
|
44
|
+
the records that number counted: Status is Cancelled. Everything else in this table is being
|
|
45
|
+
held back"*, and it still refuses to claim narrowing when no question came with the click.
|
|
46
|
+
* **`filterInWords`** turns the question into the words of the person whose business it is —
|
|
47
|
+
the Field's own name through the same `fieldName` the column headers use, never a column
|
|
48
|
+
key. `null` becomes "Status is not filled in"; a window becomes "from … up to …", because
|
|
49
|
+
the store's windows are half-open and "to 2026-02-01" would read as including February 1st.
|
|
50
|
+
* **`DigestScheduler.filters` is a `RecordFilter`**, and `DashboardCanvas`'s
|
|
51
|
+
`as Record<string, unknown>` is gone — that cast was the seam where the dashboard's filter,
|
|
52
|
+
the saved view it schedules over and the drill-through it opens could have drifted apart.
|
|
53
|
+
* **Guard `a-number-opens-only-its-own-rows.test.tsx`** asserts the DOOR the page opened and
|
|
54
|
+
the argument it carried, and refuses by name the moment anything opens the unfiltered
|
|
55
|
+
`read_records` while holding a filter. Shown RED on the pre-fix bytes (four clauses,
|
|
56
|
+
including the old sentence) and green on these.
|
|
57
|
+
|
|
3
58
|
## 0.69.0
|
|
4
59
|
|
|
5
60
|
**She can make the one that is missing, from where she is looking for it.** (lane TAILS-7.)
|
package/dist/index.cjs
CHANGED
|
@@ -919,8 +919,9 @@ var import_react5 = require("react");
|
|
|
919
919
|
var import_react6 = require("@ai-matrx/records/react");
|
|
920
920
|
var import_design_system2 = require("@ai-matrx/design-system");
|
|
921
921
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
922
|
+
var NO_STORE_ON_THIS_SCREEN_REASON = "cannot be answered on this page: it points at a record in somebody's own data, and a page answered without an account is never allowed to search that. Leave it blank and whoever receives this will fill it in.";
|
|
922
923
|
function RelationPicker({ field, value, onChange, disabled, id, className, allowCreate = true }) {
|
|
923
|
-
const client = (0, import_react6.
|
|
924
|
+
const client = (0, import_react6.useOptionalRecordsClient)();
|
|
924
925
|
const [rows, setRows] = (0, import_react5.useState)(null);
|
|
925
926
|
const [words, setWords] = (0, import_react5.useState)({});
|
|
926
927
|
const [refusal, setRefusal] = (0, import_react5.useState)(null);
|
|
@@ -938,7 +939,7 @@ function RelationPicker({ field, value, onChange, disabled, id, className, allow
|
|
|
938
939
|
);
|
|
939
940
|
(0, import_react5.useEffect)(() => {
|
|
940
941
|
const target2 = field.relation_target;
|
|
941
|
-
if (!target2) return;
|
|
942
|
+
if (!target2 || !client) return;
|
|
942
943
|
let cancelled = false;
|
|
943
944
|
void client.list({ table_id: target2, limit: 200 }).then((result) => {
|
|
944
945
|
if (cancelled) return;
|
|
@@ -950,7 +951,7 @@ function RelationPicker({ field, value, onChange, disabled, id, className, allow
|
|
|
950
951
|
};
|
|
951
952
|
}, [client, field.relation_target]);
|
|
952
953
|
(0, import_react5.useEffect)(() => {
|
|
953
|
-
if (!rows) return;
|
|
954
|
+
if (!rows || !client) return;
|
|
954
955
|
const wanted = [.../* @__PURE__ */ new Set([...rows.map((row) => row.id), ...picked])].filter(
|
|
955
956
|
(id2) => words[id2] === void 0
|
|
956
957
|
);
|
|
@@ -970,7 +971,7 @@ function RelationPicker({ field, value, onChange, disabled, id, className, allow
|
|
|
970
971
|
};
|
|
971
972
|
}, [client, field.id, rows, picked, words]);
|
|
972
973
|
(0, import_react5.useEffect)(() => {
|
|
973
|
-
if (!open || !allowCreate || target || targetRefusal) return;
|
|
974
|
+
if (!open || !allowCreate || target || targetRefusal || !client) return;
|
|
974
975
|
const id2 = field.relation_target;
|
|
975
976
|
if (!id2) return;
|
|
976
977
|
let cancelled = false;
|
|
@@ -991,6 +992,13 @@ function RelationPicker({ field, value, onChange, disabled, id, className, allow
|
|
|
991
992
|
cancelled = true;
|
|
992
993
|
};
|
|
993
994
|
}, [client, open, allowCreate, target, targetRefusal, field.relation_target]);
|
|
995
|
+
if (!client) {
|
|
996
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { id, className: (0, import_design_system2.cn)("text-xs text-muted-foreground", className), children: [
|
|
997
|
+
fieldName(field),
|
|
998
|
+
" ",
|
|
999
|
+
NO_STORE_ON_THIS_SCREEN_REASON
|
|
1000
|
+
] });
|
|
1001
|
+
}
|
|
994
1002
|
if (!field.relation_target) {
|
|
995
1003
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
|
|
996
1004
|
fieldName(field),
|
|
@@ -1321,10 +1329,11 @@ function JsonControl({ field, value, onChange, disabled, id }) {
|
|
|
1321
1329
|
] });
|
|
1322
1330
|
}
|
|
1323
1331
|
function OptionControl({ field, value, onChange, disabled, id }) {
|
|
1324
|
-
const client = (0, import_react8.
|
|
1332
|
+
const client = (0, import_react8.useOptionalRecordsClient)();
|
|
1325
1333
|
const [options, setOptions] = (0, import_react7.useState)(null);
|
|
1326
1334
|
const [refusal, setRefusal] = (0, import_react7.useState)(null);
|
|
1327
1335
|
(0, import_react7.useEffect)(() => {
|
|
1336
|
+
if (!client) return;
|
|
1328
1337
|
let cancelled = false;
|
|
1329
1338
|
void client.fieldOptions({ field_id: field.id }).then((result) => {
|
|
1330
1339
|
if (cancelled) return;
|
|
@@ -1335,6 +1344,23 @@ function OptionControl({ field, value, onChange, disabled, id }) {
|
|
|
1335
1344
|
cancelled = true;
|
|
1336
1345
|
};
|
|
1337
1346
|
}, [client, field.id]);
|
|
1347
|
+
if (!client) {
|
|
1348
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1350
|
+
import_design_system3.BasicInput,
|
|
1351
|
+
{
|
|
1352
|
+
id,
|
|
1353
|
+
value: value === null || value === void 0 ? "" : String(value),
|
|
1354
|
+
disabled,
|
|
1355
|
+
onChange: (e) => onChange(e.target.value === "" ? null : e.target.value)
|
|
1356
|
+
}
|
|
1357
|
+
),
|
|
1358
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
|
|
1359
|
+
fieldName(field),
|
|
1360
|
+
" is normally picked from a list. This page is answered without an account, so the list cannot be read here \u2014 type your answer and whoever receives it will match it up."
|
|
1361
|
+
] })
|
|
1362
|
+
] });
|
|
1363
|
+
}
|
|
1338
1364
|
if (refusal) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { id, className: "text-xs text-destructive", children: refusal });
|
|
1339
1365
|
if (!options) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { id, className: "text-xs text-muted-foreground", children: "Reading this field's choices\u2026" });
|
|
1340
1366
|
if (options.length === 0) {
|
|
@@ -1419,7 +1445,7 @@ async function personRecordForMember(client, personTableId, people, member) {
|
|
|
1419
1445
|
return written;
|
|
1420
1446
|
}
|
|
1421
1447
|
function PersonPicker({ field, value, onChange, disabled, id, className }) {
|
|
1422
|
-
const client = (0, import_react10.
|
|
1448
|
+
const client = (0, import_react10.useOptionalRecordsClient)();
|
|
1423
1449
|
const host = useRecordsUi();
|
|
1424
1450
|
const [members, setMembers] = (0, import_react9.useState)(null);
|
|
1425
1451
|
const [people, setPeople] = (0, import_react9.useState)([]);
|
|
@@ -1434,7 +1460,7 @@ function PersonPicker({ field, value, onChange, disabled, id, className }) {
|
|
|
1434
1460
|
[value]
|
|
1435
1461
|
);
|
|
1436
1462
|
const load = (0, import_react9.useCallback)(async () => {
|
|
1437
|
-
if (!membersPort) return;
|
|
1463
|
+
if (!membersPort || !client) return;
|
|
1438
1464
|
const [roster, records] = await Promise.all([
|
|
1439
1465
|
membersPort(),
|
|
1440
1466
|
personTable ? client.list({ table_id: personTable, limit: 500 }) : Promise.resolve(null)
|
|
@@ -1451,7 +1477,7 @@ function PersonPicker({ field, value, onChange, disabled, id, className }) {
|
|
|
1451
1477
|
void load();
|
|
1452
1478
|
}, [open, load]);
|
|
1453
1479
|
(0, import_react9.useEffect)(() => {
|
|
1454
|
-
if (picked.length === 0 || !personTable || people.length > 0) return;
|
|
1480
|
+
if (picked.length === 0 || !personTable || people.length > 0 || !client) return;
|
|
1455
1481
|
let cancelled = false;
|
|
1456
1482
|
void client.list({ table_id: personTable, limit: 500 }).then((result) => {
|
|
1457
1483
|
if (cancelled || !result.ok) return;
|
|
@@ -1461,7 +1487,7 @@ function PersonPicker({ field, value, onChange, disabled, id, className }) {
|
|
|
1461
1487
|
cancelled = true;
|
|
1462
1488
|
};
|
|
1463
1489
|
}, [client, personTable, picked.length, people.length]);
|
|
1464
|
-
if (!membersPort) {
|
|
1490
|
+
if (!membersPort || !client) {
|
|
1465
1491
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: (0, import_design_system4.cn)("text-xs text-muted-foreground", className), children: NO_MEMBERS_REASON });
|
|
1466
1492
|
}
|
|
1467
1493
|
if (!personTable) {
|
|
@@ -3557,6 +3583,7 @@ var NO_COLUMNS_WHY = "A column is what a record holds \u2014 a name, a date, an
|
|
|
3557
3583
|
function Grid({
|
|
3558
3584
|
tableId,
|
|
3559
3585
|
pageSize = 50,
|
|
3586
|
+
filter,
|
|
3560
3587
|
onOpenRecord,
|
|
3561
3588
|
onAddField,
|
|
3562
3589
|
onNewRecordForm,
|
|
@@ -3572,7 +3599,7 @@ function Grid({
|
|
|
3572
3599
|
const table = (0, import_react21.useTable)(tableId);
|
|
3573
3600
|
const fields = (0, import_react21.useFields)(tableId);
|
|
3574
3601
|
const [page, setPage] = (0, import_react20.useState)(0);
|
|
3575
|
-
const records = (0, import_react21.useRecords)(tableId, { pageSize, page });
|
|
3602
|
+
const records = (0, import_react21.useRecords)(tableId, { pageSize, page, ...filter ? { filter } : {} });
|
|
3576
3603
|
const rights = useTableRights(table.data);
|
|
3577
3604
|
const rows = (0, import_react20.useMemo)(() => records.data?.rows ?? [], [records.data]);
|
|
3578
3605
|
const rowIds = (0, import_react20.useMemo)(() => rows.map((row) => row.id), [rows]);
|
|
@@ -7321,9 +7348,12 @@ function unplacedName(record, field, labels) {
|
|
|
7321
7348
|
// src/ViewSwitcher.tsx
|
|
7322
7349
|
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
7323
7350
|
var NO_FIELDS = [];
|
|
7324
|
-
function useViewRecords(view, pageSize = 200) {
|
|
7351
|
+
function useViewRecords(view, pageSize = 200, filter) {
|
|
7325
7352
|
const client = (0, import_react49.useRecordsClient)();
|
|
7326
|
-
const table = (0, import_react49.useRecords)(view.ruleId ? null : view.subject, {
|
|
7353
|
+
const table = (0, import_react49.useRecords)(view.ruleId ? null : view.subject, {
|
|
7354
|
+
pageSize,
|
|
7355
|
+
...filter ? { filter } : {}
|
|
7356
|
+
});
|
|
7327
7357
|
const [ruled, setRuled] = (0, import_react48.useState)({
|
|
7328
7358
|
rows: [],
|
|
7329
7359
|
loading: Boolean(view.ruleId),
|
|
@@ -7378,6 +7408,7 @@ function ViewSwitcher({
|
|
|
7378
7408
|
onNewRecordForm,
|
|
7379
7409
|
onAskWhoChanged,
|
|
7380
7410
|
pageSize = 200,
|
|
7411
|
+
filter,
|
|
7381
7412
|
className
|
|
7382
7413
|
}) {
|
|
7383
7414
|
const [layout, setLayout] = (0, import_react48.useState)(view.layout);
|
|
@@ -7415,6 +7446,7 @@ function ViewSwitcher({
|
|
|
7415
7446
|
{
|
|
7416
7447
|
tableId: view.subject,
|
|
7417
7448
|
pageSize,
|
|
7449
|
+
...filter ? { filter } : {},
|
|
7418
7450
|
...local.presentation ?? view.presentation ? { presentation: local.presentation ?? view.presentation } : {},
|
|
7419
7451
|
...onViewChange ? { onPresentationChange: (next) => change({ presentation: next }) } : {},
|
|
7420
7452
|
...onOpenRecord ? { onOpenRecord } : {},
|
|
@@ -7426,6 +7458,7 @@ function ViewSwitcher({
|
|
|
7426
7458
|
{
|
|
7427
7459
|
view: { ...view, ...local, layout },
|
|
7428
7460
|
pageSize,
|
|
7461
|
+
...filter ? { filter } : {},
|
|
7429
7462
|
onChange: change,
|
|
7430
7463
|
remembered: Boolean(onViewChange),
|
|
7431
7464
|
...onOpenRecord ? { onOpenRecord } : {},
|
|
@@ -7473,13 +7506,14 @@ function boardColumnChoice(fields, chosenKey, stage) {
|
|
|
7473
7506
|
function Board({
|
|
7474
7507
|
view,
|
|
7475
7508
|
pageSize,
|
|
7509
|
+
filter,
|
|
7476
7510
|
onChange,
|
|
7477
7511
|
remembered,
|
|
7478
7512
|
onOpenRecord,
|
|
7479
7513
|
onMoved
|
|
7480
7514
|
}) {
|
|
7481
7515
|
const fields = (0, import_react49.useFields)(view.subject);
|
|
7482
|
-
const records = useViewRecords(view, pageSize);
|
|
7516
|
+
const records = useViewRecords(view, pageSize, filter);
|
|
7483
7517
|
const stage = useStageField(view.subject);
|
|
7484
7518
|
if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(RefusalNotice, { error: fields.error });
|
|
7485
7519
|
if (records.error) return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(RefusalNotice, { error: records.error });
|
|
@@ -13000,14 +13034,20 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
|
|
|
13000
13034
|
rights.admin ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Button, { size: "sm", variant: "ghost", onClick: () => void remove(board), children: "Delete" }) : null
|
|
13001
13035
|
] }) : null
|
|
13002
13036
|
] }),
|
|
13003
|
-
board && scheduling ?
|
|
13004
|
-
|
|
13005
|
-
|
|
13006
|
-
|
|
13007
|
-
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
13037
|
+
board && scheduling ? (
|
|
13038
|
+
// ONE SHAPE, SO NO CAST. The dashboard's own filter, the saved view it
|
|
13039
|
+
// schedules over and the drill-through it opens are all the same
|
|
13040
|
+
// `RecordFilter`; the `as Record<string, unknown>` that used to be here
|
|
13041
|
+
// was the seam where they could have drifted.
|
|
13042
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
13043
|
+
DigestScheduler,
|
|
13044
|
+
{
|
|
13045
|
+
tableId,
|
|
13046
|
+
subjectName: board.name,
|
|
13047
|
+
...filter ? { filters: filter } : {},
|
|
13048
|
+
onClose: () => setScheduling(false)
|
|
13049
|
+
}
|
|
13050
|
+
)
|
|
13011
13051
|
) : null,
|
|
13012
13052
|
board ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
13013
13053
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
@@ -15007,9 +15047,35 @@ var import_react111 = require("react");
|
|
|
15007
15047
|
var import_react112 = require("@ai-matrx/records/react");
|
|
15008
15048
|
var import_design_system54 = require("@ai-matrx/design-system");
|
|
15009
15049
|
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
15010
|
-
function
|
|
15011
|
-
const
|
|
15012
|
-
|
|
15050
|
+
function filterInWords(filter, fields) {
|
|
15051
|
+
const nameOf = (key) => {
|
|
15052
|
+
const field = fields.find((f) => f.key === key);
|
|
15053
|
+
return field ? fieldName(field) : humanize(key);
|
|
15054
|
+
};
|
|
15055
|
+
const parts = Object.keys(filter).map((key) => {
|
|
15056
|
+
const value = filter[key];
|
|
15057
|
+
if (value === null || value === void 0) return `${nameOf(key)} is not filled in`;
|
|
15058
|
+
if (typeof value === "object") {
|
|
15059
|
+
const from = (value.from ?? "").toString().trim();
|
|
15060
|
+
const to = (value.to ?? "").toString().trim();
|
|
15061
|
+
if (from !== "" && to !== "") return `${nameOf(key)} from ${from} up to ${to}`;
|
|
15062
|
+
if (from !== "") return `${nameOf(key)} from ${from} onwards`;
|
|
15063
|
+
if (to !== "") return `${nameOf(key)} up to ${to}`;
|
|
15064
|
+
return `${nameOf(key)} in a period nobody named`;
|
|
15065
|
+
}
|
|
15066
|
+
return `${nameOf(key)} is ${String(value)}`;
|
|
15067
|
+
});
|
|
15068
|
+
if (parts.length === 0) return "";
|
|
15069
|
+
if (parts.length === 1) return parts[0];
|
|
15070
|
+
return `${parts.slice(0, -1).join(", ")} and ${parts[parts.length - 1]}`;
|
|
15071
|
+
}
|
|
15072
|
+
function cameFromLine(label, groupField, question) {
|
|
15073
|
+
const asked = (question ?? "").trim();
|
|
15074
|
+
if (asked === "") {
|
|
15075
|
+
const grouped = groupField ? " grouped into the same columns the chart used" : "";
|
|
15076
|
+
return `You came here from \u201C${label}\u201D. This is every record in this table${grouped} \u2014 that number was counted over all of them.`;
|
|
15077
|
+
}
|
|
15078
|
+
return `You came here from \u201C${label}\u201D. These are only the records that number counted: ${asked}. Everything else in this table is being held back \u2014 clear the filter to see all of it.`;
|
|
15013
15079
|
}
|
|
15014
15080
|
var TABLE_NOT_REACHABLE = "This table is not in the organization you are working in, so there is nothing here to show. Switch to the organization that owns it and open it again \u2014 or it may have been deleted.";
|
|
15015
15081
|
var DEFAULT_VIEW_NAME = "All records";
|
|
@@ -15056,11 +15122,14 @@ function TablePage({
|
|
|
15056
15122
|
onViewChanged,
|
|
15057
15123
|
activeGroupField,
|
|
15058
15124
|
cameFrom,
|
|
15125
|
+
filter,
|
|
15059
15126
|
className
|
|
15060
15127
|
}) {
|
|
15061
15128
|
const client = (0, import_react112.useRecordsClient)();
|
|
15062
15129
|
const table = (0, import_react112.useTable)(tableId);
|
|
15063
15130
|
const rights = useTableRights(table.data);
|
|
15131
|
+
const pageFields = (0, import_react112.useFields)(filter ? tableId : null);
|
|
15132
|
+
const askedInWords = filter ? filterInWords(filter, pageFields.data ?? []) : null;
|
|
15064
15133
|
const organizationId = (0, import_react112.useRecordsClient)().config.organizationId;
|
|
15065
15134
|
const [view, setView] = (0, import_react111.useState)(null);
|
|
15066
15135
|
const opening = openingRail(activeRecordId);
|
|
@@ -15254,7 +15323,7 @@ function TablePage({
|
|
|
15254
15323
|
{
|
|
15255
15324
|
"data-testid": "came-from-a-number",
|
|
15256
15325
|
className: "rounded-md border px-3 py-2 text-xs leading-relaxed text-muted-foreground",
|
|
15257
|
-
children: cameFromLine(cameFrom, activeGroupField ?? null)
|
|
15326
|
+
children: cameFromLine(cameFrom, activeGroupField ?? null, askedInWords)
|
|
15258
15327
|
}
|
|
15259
15328
|
) : null,
|
|
15260
15329
|
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
@@ -15268,6 +15337,7 @@ function TablePage({
|
|
|
15268
15337
|
...activeGroupField ? { groupField: activeGroupField } : {}
|
|
15269
15338
|
},
|
|
15270
15339
|
pageSize,
|
|
15340
|
+
...filter ? { filter } : {},
|
|
15271
15341
|
onLayoutChange: (layout) => {
|
|
15272
15342
|
setLayoutFromLink(layout);
|
|
15273
15343
|
onViewChanged?.(layout);
|