@ai-matrx/records-ui 0.113.30 → 0.113.32
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 +48 -1
- package/dist/first-page.cjs +73 -585
- package/dist/first-page.cjs.map +1 -1
- package/dist/first-page.d.cts +17 -251
- package/dist/first-page.d.ts +17 -251
- package/dist/first-page.js +24 -582
- package/dist/first-page.js.map +1 -1
- package/dist/index.cjs +6520 -7879
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -827
- package/dist/index.d.ts +54 -827
- package/dist/index.js +7675 -8954
- package/dist/index.js.map +1 -1
- package/dist/pickers.cjs +1619 -1605
- package/dist/pickers.cjs.map +1 -1
- package/dist/pickers.js +1498 -1470
- package/dist/pickers.js.map +1 -1
- package/package.json +5 -6
package/dist/first-page.js
CHANGED
|
@@ -1,265 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import 'react';
|
|
7
|
-
import { parseTableStyle, tableStyleIsEmpty } from '@ai-matrx/design-system/data-table/table-style';
|
|
1
|
+
import { bindFirstPageCodec } from '@ai-matrx/records/first-page';
|
|
2
|
+
export { EMBEDDED_PAGE_SIZE, TABLE_PAGE_SIZE, askChartSeed, askEntityBlockSeed, askTileSeed, firstGridPageArgs, mergeSeeds, serverRowsOf, viewFilterOf } from '@ai-matrx/records/first-page';
|
|
3
|
+
import * as base from '@ai-matrx/records/views';
|
|
4
|
+
import { tableStyleIsEmpty, parseTableStyle } from '@ai-matrx/design-system/data-table/table-style';
|
|
5
|
+
import '@ai-matrx/design-system/data-table';
|
|
8
6
|
import '@ai-matrx/design-system/field-formats';
|
|
9
|
-
import
|
|
7
|
+
import '@ai-matrx/records';
|
|
10
8
|
|
|
11
9
|
// src/firstPage.ts
|
|
12
|
-
function fieldName(field2) {
|
|
13
|
-
const label = (field2.label ?? "").trim();
|
|
14
|
-
if (label !== "" && label === field2.key && /^[a-z0-9]+(?:[_.-][a-z0-9]+)+$/.test(label)) return humanizeIdentifier(label);
|
|
15
|
-
if (label !== "") return label;
|
|
16
|
-
const name = (field2.name ?? "").trim();
|
|
17
|
-
if (name !== "") return name;
|
|
18
|
-
return humanizeIdentifier(field2.key);
|
|
19
|
-
}
|
|
20
|
-
var kernelId = (name) => KERNEL_TABLES.find((t) => t.name === name)?.id ?? "";
|
|
21
|
-
var KERNEL_FILE_TABLE = kernelId("File");
|
|
22
|
-
var KERNEL_PERSON_TABLE = kernelId("Person");
|
|
23
|
-
Object.fromEntries(
|
|
24
|
-
PARITY_FIELD_TYPES.map((p) => [p.parity_type, p.made_of])
|
|
25
|
-
);
|
|
26
|
-
var KERNEL = { file: KERNEL_FILE_TABLE, person: KERNEL_PERSON_TABLE };
|
|
27
|
-
function editorKindFor(field2) {
|
|
28
|
-
return fieldKindFor(field2, KERNEL);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// src/gridLook.ts
|
|
32
|
-
function defaultSortOf(table, fields) {
|
|
33
|
-
const raw = table?.default_sort ?? null;
|
|
34
|
-
const first = Array.isArray(raw) ? raw[0] : raw;
|
|
35
|
-
let name = null;
|
|
36
|
-
let direction = "asc";
|
|
37
|
-
if (typeof first === "string") {
|
|
38
|
-
const trimmed = first.trim();
|
|
39
|
-
if (trimmed === "") return null;
|
|
40
|
-
if (trimmed.startsWith("-")) {
|
|
41
|
-
name = trimmed.slice(1).trim();
|
|
42
|
-
direction = "desc";
|
|
43
|
-
} else {
|
|
44
|
-
const [head, tail] = trimmed.split(/\s+/);
|
|
45
|
-
name = head ?? null;
|
|
46
|
-
if (tail && tail.toLowerCase() === "desc") direction = "desc";
|
|
47
|
-
}
|
|
48
|
-
} else if (first && typeof first === "object") {
|
|
49
|
-
const entry = first;
|
|
50
|
-
const named = entry["field"] ?? entry["key"] ?? entry["id"];
|
|
51
|
-
name = typeof named === "string" ? named : null;
|
|
52
|
-
if (String(entry["direction"] ?? "").toLowerCase() === "desc") direction = "desc";
|
|
53
|
-
}
|
|
54
|
-
if (!name) return null;
|
|
55
|
-
const field2 = fields.find((f) => f.key === name) ?? fields.find((f) => f.id === name);
|
|
56
|
-
return field2 ? { id: field2.key, direction } : null;
|
|
57
|
-
}
|
|
58
|
-
var MEASURE_LABEL = {
|
|
59
|
-
count: "Count",
|
|
60
|
-
sum: "Sum",
|
|
61
|
-
avg: "Average",
|
|
62
|
-
min: "Smallest",
|
|
63
|
-
max: "Largest",
|
|
64
|
-
median: "Median",
|
|
65
|
-
filled: "Filled",
|
|
66
|
-
empty: "Empty",
|
|
67
|
-
unique: "Unique",
|
|
68
|
-
percent_empty: "Percent empty",
|
|
69
|
-
percent_filled: "Percent filled",
|
|
70
|
-
range: "Range"
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
// src/gridPage.ts
|
|
74
|
-
function filterRefusal(f) {
|
|
75
|
-
if (!computedOnRead(f)) return null;
|
|
76
|
-
return `${fieldName(f)} is worked out each time it is read, so the store keeps no value to filter the whole table by. Filter by a column it is worked out from.`;
|
|
77
|
-
}
|
|
78
|
-
function computedOnRead(f) {
|
|
79
|
-
const kind = String(editorKindFor(f));
|
|
80
|
-
return (f.type === "formula" || kind === "formula" || kind === "lookup" || kind === "rollup") && String(f.compute_on ?? "read") === "read";
|
|
81
|
-
}
|
|
82
|
-
function holdsNumbers(field2) {
|
|
83
|
-
const kind = String(editorKindFor(field2));
|
|
84
|
-
if (kind === "number" || kind === "currency" || kind === "percent") return true;
|
|
85
|
-
return String((field2.config ?? {})["system"] ?? "") === "autonumber";
|
|
86
|
-
}
|
|
87
|
-
function sortAsFor(field2) {
|
|
88
|
-
const kind = String(editorKindFor(field2));
|
|
89
|
-
if (holdsNumbers(field2)) return "number";
|
|
90
|
-
if (kind === "datetime") return "date";
|
|
91
|
-
return "text";
|
|
92
|
-
}
|
|
93
|
-
function pageSortFor(fields, sort) {
|
|
94
|
-
if (!sort) return [];
|
|
95
|
-
const field2 = fields.find((f) => f.key === sort.id);
|
|
96
|
-
if (!field2) return [];
|
|
97
|
-
return [{ field: field2.key, direction: sort.direction === "desc" ? "desc" : "asc", as: sortAsFor(field2) }];
|
|
98
|
-
}
|
|
99
|
-
function containsPattern(text) {
|
|
100
|
-
return `(?i)${text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`;
|
|
101
|
-
}
|
|
102
|
-
var BLANK_VALUE = "__empty__";
|
|
103
|
-
var field = (f) => ({ field: f.id });
|
|
104
|
-
var constant = (value) => ({ const: value });
|
|
105
|
-
var withinWindow = (f, window) => ({ op: "within", args: [field(f), constant(window)] });
|
|
106
|
-
var op = (name, ...args) => ({ op: name, args });
|
|
107
|
-
function clauseFor(f, value, now = /* @__PURE__ */ new Date()) {
|
|
108
|
-
const name = fieldName(f);
|
|
109
|
-
const refused = filterRefusal(f);
|
|
110
|
-
if (refused) return refused;
|
|
111
|
-
const not = (rule) => op("not", rule);
|
|
112
|
-
switch (value.kind) {
|
|
113
|
-
case "text": {
|
|
114
|
-
const mode = value.mode ?? "contains";
|
|
115
|
-
if (mode === "empty" || mode === "null") return value.negated ? { rule: op("present", field(f)) } : { rule: not(op("present", field(f))) };
|
|
116
|
-
if (mode === "not_empty" || mode === "not_null") return value.negated ? { rule: not(op("present", field(f))) } : { rule: op("present", field(f)) };
|
|
117
|
-
const text = value.value.trim();
|
|
118
|
-
if (text === "") return null;
|
|
119
|
-
const kind = String(editorKindFor(f));
|
|
120
|
-
if (kind === "number" || kind === "currency" || kind === "percent" || kind === "checkbox") {
|
|
121
|
-
return `${name} holds numbers, so it is filtered by a range, not by words.`;
|
|
122
|
-
}
|
|
123
|
-
const matches = op("matches", field(f), constant(containsPattern(text)));
|
|
124
|
-
return { rule: value.negated ? not(matches) : matches };
|
|
125
|
-
}
|
|
126
|
-
case "select": {
|
|
127
|
-
const ticked = value.values ?? (value.value === "" ? [] : [value.value]);
|
|
128
|
-
const blank = ticked.includes(BLANK_VALUE);
|
|
129
|
-
const words = ticked.filter((w) => w !== BLANK_VALUE);
|
|
130
|
-
if (!blank && words.length === 0) return value.negated ? null : { rule: constant(false) };
|
|
131
|
-
const present = op("present", field(f));
|
|
132
|
-
const kind = String(editorKindFor(f));
|
|
133
|
-
if (kind === "datetime" || kind === "date") {
|
|
134
|
-
if (words.length === 0) return { rule: value.negated ? present : not(present) };
|
|
135
|
-
const holdsDays = String((f.config ?? {})["kind"] ?? "") === "date";
|
|
136
|
-
if (words.length === 1 && !blank && !value.negated) return { flat: { [f.key]: dayWindow(words[0], holdsDays) } };
|
|
137
|
-
const leaves = words.map((day) => withinWindow(f, dayWindow(day, holdsDays)));
|
|
138
|
-
const anyDay = leaves.length === 1 ? leaves[0] : op("or", ...leaves);
|
|
139
|
-
if (!value.negated) return { rule: blank ? op("or", not(present), anyDay) : anyDay };
|
|
140
|
-
return { rule: blank ? op("and", present, not(anyDay)) : not(anyDay) };
|
|
141
|
-
}
|
|
142
|
-
const asStored = (w) => holdsNumbers(f) || kind === "rating" ? Number.isFinite(Number(w)) ? Number(w) : w : kind === "checkbox" && (w === "true" || w === "false") ? w === "true" : w;
|
|
143
|
-
const stored = words.map(asStored);
|
|
144
|
-
const anyWord = stored.length === 0 ? null : stored.length === 1 ? op("eq", field(f), constant(stored[0])) : op("or", ...stored.map((w) => op("eq", field(f), constant(w))));
|
|
145
|
-
if (!value.negated) {
|
|
146
|
-
if (!blank && stored.length === 1) return { flat: { [f.key]: stored[0] } };
|
|
147
|
-
if (!blank) return { rule: anyWord };
|
|
148
|
-
return { rule: anyWord ? op("or", not(present), anyWord) : not(present) };
|
|
149
|
-
}
|
|
150
|
-
if (blank) return { rule: anyWord ? op("and", present, not(anyWord)) : present };
|
|
151
|
-
return { rule: op("or", not(present), not(anyWord)) };
|
|
152
|
-
}
|
|
153
|
-
case "boolean":
|
|
154
|
-
return value.negated ? { rule: op("ne", field(f), constant(value.value)) } : { flat: { [f.key]: value.value } };
|
|
155
|
-
case "number": {
|
|
156
|
-
const turned = (rule) => ({ rule: value.negated ? not(rule) : rule });
|
|
157
|
-
if (value.op === "empty") return turned(not(op("present", field(f))));
|
|
158
|
-
if (value.op === "not_empty") return turned(op("present", field(f)));
|
|
159
|
-
if (value.op === "eq" || value.op === "ne") {
|
|
160
|
-
if (typeof value.min !== "number") return null;
|
|
161
|
-
return turned(op(value.op, field(f), constant(value.min)));
|
|
162
|
-
}
|
|
163
|
-
if (value.op === "lt") return typeof value.max === "number" ? turned(op("lt", field(f), constant(value.max))) : null;
|
|
164
|
-
if (value.op === "gt") return typeof value.min === "number" ? turned(op("gt", field(f), constant(value.min))) : null;
|
|
165
|
-
const parts = [];
|
|
166
|
-
if (typeof value.min === "number") parts.push(op("gte", field(f), constant(value.min)));
|
|
167
|
-
if (typeof value.max === "number") parts.push(op("lte", field(f), constant(value.max)));
|
|
168
|
-
if (parts.length === 0) return null;
|
|
169
|
-
const range = parts.length === 1 ? parts[0] : op("and", ...parts);
|
|
170
|
-
return { rule: value.negated ? not(range) : range };
|
|
171
|
-
}
|
|
172
|
-
case "date": {
|
|
173
|
-
const zone2 = void 0;
|
|
174
|
-
const moments = dateFilterBounds(value.preset ? { ...value, anchor: now.toISOString() } : value, now, zone2);
|
|
175
|
-
const holdsDays = String((f.config ?? {})["kind"] ?? "") === "date";
|
|
176
|
-
const bounds = holdsDays ? dateFilterDayBounds(moments, zone2) : moments;
|
|
177
|
-
if (bounds.since === void 0 && bounds.until === void 0) return null;
|
|
178
|
-
return {
|
|
179
|
-
flat: {
|
|
180
|
-
[f.key]: {
|
|
181
|
-
...bounds.since === void 0 ? {} : { from: bounds.since },
|
|
182
|
-
...bounds.until === void 0 ? {} : { to: bounds.until }
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
default:
|
|
188
|
-
return `${name} cannot be filtered that way by the store.`;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
function dayWindow(day, holdsDays) {
|
|
192
|
-
if (!holdsDays) return dayInstantWindow(day, void 0);
|
|
193
|
-
const [y, m, d] = day.split("-").map(Number);
|
|
194
|
-
const ymd = (t) => `${t.getUTCFullYear()}-${String(t.getUTCMonth() + 1).padStart(2, "0")}-${String(t.getUTCDate()).padStart(2, "0")}`;
|
|
195
|
-
return { from: ymd(new Date(Date.UTC(y, (m ?? 1) - 1, d ?? 1))), to: ymd(new Date(Date.UTC(y, (m ?? 1) - 1, (d ?? 1) + 1))) };
|
|
196
|
-
}
|
|
197
|
-
function storeQuestion(fields, base, columnFilters, now = /* @__PURE__ */ new Date()) {
|
|
198
|
-
const refused = [];
|
|
199
|
-
const flat = {};
|
|
200
|
-
const rules = [];
|
|
201
|
-
if (base && isRuleFilter(base)) rules.push(base);
|
|
202
|
-
else if (base) Object.assign(flat, base);
|
|
203
|
-
for (const [key, value] of Object.entries(columnFilters)) {
|
|
204
|
-
if (!value) continue;
|
|
205
|
-
const f = fields.find((candidate) => candidate.key === key);
|
|
206
|
-
if (!f) continue;
|
|
207
|
-
const clause = clauseFor(f, value, now);
|
|
208
|
-
if (clause === null) continue;
|
|
209
|
-
if (typeof clause === "string") {
|
|
210
|
-
refused.push(clause);
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
if ("flat" in clause) Object.assign(flat, clause.flat);
|
|
214
|
-
else rules.push(clause.rule);
|
|
215
|
-
}
|
|
216
|
-
const flatKeys = Object.keys(flat);
|
|
217
|
-
if (rules.length === 0) return { filter: flatKeys.length > 0 ? flat : void 0, refused };
|
|
218
|
-
for (const key of flatKeys) {
|
|
219
|
-
const f = fields.find((candidate) => candidate.key === key);
|
|
220
|
-
const value = flat[key];
|
|
221
|
-
if (!f) continue;
|
|
222
|
-
if (value !== null && typeof value === "object") {
|
|
223
|
-
rules.push(withinWindow(f, value));
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
rules.push(value === null ? op("not", op("present", field(f))) : op("eq", field(f), constant(value)));
|
|
227
|
-
}
|
|
228
|
-
return { filter: rules.length === 1 ? rules[0] : op("and", ...rules), refused };
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// src/rowVersion.ts
|
|
232
|
-
function ownVersion(row) {
|
|
233
|
-
const v = row.version;
|
|
234
|
-
return typeof v === "number" ? v : null;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// src/groupReads.ts
|
|
238
|
-
function isPlainGrouping(grouping) {
|
|
239
|
-
return Boolean(grouping) && !(grouping.then && grouping.then.length > 0) && !grouping.across && !(grouping.trail && grouping.trail.length > 0);
|
|
240
|
-
}
|
|
241
|
-
function groupedPageSort(fields, groupKey, sort) {
|
|
242
|
-
if (!groupKey) return sort;
|
|
243
|
-
const field2 = fields.find((f) => f.key === groupKey);
|
|
244
|
-
if (!field2) return sort;
|
|
245
|
-
return [{ field: groupKey, direction: "asc", as: sortAsFor(field2) }, ...sort.filter((s) => s.field !== groupKey)];
|
|
246
|
-
}
|
|
247
|
-
function chosenEntries(chosen) {
|
|
248
|
-
return JSON.parse(JSON.stringify(Object.entries(chosen).sort())).filter(([, op2]) => op2 in MEASURE_LABEL);
|
|
249
|
-
}
|
|
250
|
-
function groupFactMeasures(chosen) {
|
|
251
|
-
return [{ op: "count" }, ...chosenEntries(chosen).filter(([, op2]) => op2 !== "count").map(([key, op2]) => ({ op: op2, key }))];
|
|
252
|
-
}
|
|
253
|
-
function summaryBarMeasures(chosen) {
|
|
254
|
-
return chosenEntries(chosen).map(([key, op2]) => op2 === "count" ? { op: "count" } : { op: op2, key });
|
|
255
|
-
}
|
|
256
|
-
function choiceFieldKeys(fields) {
|
|
257
|
-
return fields.filter((f) => {
|
|
258
|
-
const kind = String(editorKindFor(f));
|
|
259
|
-
return kind === "select" || kind === "multi_select";
|
|
260
|
-
}).map((f) => f.key);
|
|
261
|
-
}
|
|
262
|
-
var REVERSE_CELL_CHIPS = 3;
|
|
263
10
|
var MIN_ROW_HEIGHT = 24;
|
|
264
11
|
var MAX_ROW_HEIGHT = 96;
|
|
265
12
|
var AGGREGATE_KINDS = [
|
|
@@ -358,8 +105,8 @@ function parseGridPresentation(raw) {
|
|
|
358
105
|
if (footer === "sticky" || footer === "inline") out.footer = footer;
|
|
359
106
|
if (isRecord(value["summaries"])) {
|
|
360
107
|
const summaries = {};
|
|
361
|
-
for (const [key,
|
|
362
|
-
if (typeof
|
|
108
|
+
for (const [key, op] of Object.entries(value["summaries"])) {
|
|
109
|
+
if (typeof op === "string" && op.trim() !== "") summaries[key] = op;
|
|
363
110
|
}
|
|
364
111
|
if (Object.keys(summaries).length > 0) out.summaries = summaries;
|
|
365
112
|
}
|
|
@@ -367,9 +114,9 @@ function parseGridPresentation(raw) {
|
|
|
367
114
|
}
|
|
368
115
|
function parseGrouping(raw) {
|
|
369
116
|
if (!isRecord(raw)) return void 0;
|
|
370
|
-
const
|
|
371
|
-
if (typeof
|
|
372
|
-
const out = { field
|
|
117
|
+
const field = raw["field"];
|
|
118
|
+
if (typeof field !== "string" || field.trim() === "") return void 0;
|
|
119
|
+
const out = { field };
|
|
373
120
|
if (isRecord(raw["aggregates"])) {
|
|
374
121
|
const aggregates = {};
|
|
375
122
|
for (const [key, spec] of Object.entries(raw["aggregates"])) {
|
|
@@ -427,328 +174,23 @@ function parseGrouping(raw) {
|
|
|
427
174
|
}
|
|
428
175
|
return out;
|
|
429
176
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
function viewSettings(definition, rowFilters) {
|
|
433
|
-
const data = definition ?? {};
|
|
434
|
-
const text = (key) => {
|
|
435
|
-
const v = data[key];
|
|
436
|
-
return typeof v === "string" && v !== "" ? v : null;
|
|
437
|
-
};
|
|
438
|
-
const layout = String(data["layout"] ?? "grid");
|
|
439
|
-
const flat = rowFilters ?? (isObject(data["filters"]) ? data["filters"] : null);
|
|
440
|
-
const moved = data["moved_from"];
|
|
441
|
-
return {
|
|
442
|
-
layout: KINDS.includes(layout) ? layout : "grid",
|
|
443
|
-
filters: flat && Object.keys(flat).length > 0 ? flat : null,
|
|
444
|
-
where: isRule(data["where"]) ? data["where"] : null,
|
|
445
|
-
groupField: text("group_field"),
|
|
446
|
-
swimlaneField: text("swimlane_field"),
|
|
447
|
-
collapsedColumns: Array.isArray(data["collapsed_columns"]) ? data["collapsed_columns"].filter((v) => ["string", "number", "boolean"].includes(typeof v)).map(String) : [],
|
|
448
|
-
measure: text("measure"),
|
|
449
|
-
dateField: text("date_field"),
|
|
450
|
-
startField: text("start_field"),
|
|
451
|
-
endField: text("end_field"),
|
|
452
|
-
imageField: text("image_field"),
|
|
453
|
-
sorts: parseSorts(data["sorts"]),
|
|
454
|
-
ruleId: text("rule_id"),
|
|
455
|
-
isDefault: data["is_default"] === true || data["is_default"] === "true",
|
|
456
|
-
presentation: parseGridPresentation(data["presentation"]),
|
|
457
|
-
movedFrom: isObject(moved) ? moved : null
|
|
458
|
-
};
|
|
177
|
+
function presentationIsEmpty(p) {
|
|
178
|
+
return (p.style === void 0 || tableStyleIsEmpty(p.style)) && Object.keys(p.formats ?? {}).length === 0 && (p.frozen?.length ?? 0) === 0 && p.grouping === void 0 && Object.keys(p.widths ?? {}).length === 0 && p.rowHeight === void 0 && (p.hiddenFields?.length ?? 0) === 0 && p.cardHidden === void 0 && (p.columnOrder?.length ?? 0) === 0 && p.gallerySize === void 0 && p.wrap === void 0 && p.fit === void 0 && p.freezeFirst === void 0 && p.footer === void 0 && Object.keys(p.summaries ?? {}).length === 0;
|
|
459
179
|
}
|
|
460
|
-
function
|
|
461
|
-
return
|
|
462
|
-
}
|
|
463
|
-
function isRule(raw) {
|
|
464
|
-
if (!isObject(raw)) return false;
|
|
465
|
-
const node = raw;
|
|
466
|
-
return typeof node.op === "string" && Array.isArray(node.args);
|
|
467
|
-
}
|
|
468
|
-
function parseSorts(raw) {
|
|
469
|
-
let list = raw;
|
|
470
|
-
if (typeof raw === "string") {
|
|
471
|
-
try {
|
|
472
|
-
list = raw.trim() === "" ? [] : JSON.parse(raw);
|
|
473
|
-
} catch {
|
|
474
|
-
return [];
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
if (!Array.isArray(list)) return [];
|
|
478
|
-
return list.filter((s) => isObject(s) && typeof s.field === "string").map((s) => ({ field: s.field, direction: s.direction === "desc" ? "desc" : "asc" }));
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
// src/views.ts
|
|
482
|
-
var VIEW_LAYOUTS = ["grid", "kanban", "calendar", "gallery", "timeline", "list"];
|
|
483
|
-
function viewOrderOf(definition) {
|
|
484
|
-
const raw = definition?.["order"];
|
|
485
|
-
return raw === "manual" ? "manual" : raw === "sorted" ? "sorted" : null;
|
|
486
|
-
}
|
|
487
|
-
function defaultViewOf(views) {
|
|
488
|
-
return views.find((v) => v.isDefault);
|
|
489
|
-
}
|
|
490
|
-
function viewFromRow(row) {
|
|
491
|
-
const data = row.definition ?? {};
|
|
492
|
-
const k = viewSettings(data, row.filters && Object.keys(row.filters).length > 0 ? row.filters : null);
|
|
493
|
-
const tableFromDefinition = typeof data["table_id"] === "string" && data["table_id"] !== "" ? data["table_id"] : null;
|
|
494
|
-
return {
|
|
495
|
-
id: row.view_id,
|
|
496
|
-
name: row.name || "Untitled view",
|
|
497
|
-
subject: row.table_id ?? tableFromDefinition ?? "",
|
|
498
|
-
layout: k.layout,
|
|
499
|
-
groupField: k.groupField,
|
|
500
|
-
swimlaneField: k.swimlaneField,
|
|
501
|
-
collapsedColumns: k.collapsedColumns,
|
|
502
|
-
measure: k.measure,
|
|
503
|
-
dateField: k.dateField,
|
|
504
|
-
startField: k.startField,
|
|
505
|
-
endField: k.endField,
|
|
506
|
-
imageField: k.imageField,
|
|
507
|
-
sorts: k.sorts,
|
|
508
|
-
order: viewOrderOf(data),
|
|
509
|
-
ruleId: k.ruleId,
|
|
510
|
-
...k.filters ? { filters: k.filters } : {},
|
|
511
|
-
where: k.where,
|
|
512
|
-
// The older table's own default view, carried in by the mover, IS this table's default —
|
|
513
|
-
// the mover wrote the row's column, which `custom.views` does not return. Read as anything
|
|
514
|
-
// else, the page would seed a second "All records" beside it and open on that.
|
|
515
|
-
isDefault: k.isDefault || k.movedFrom?.["kind"] === "default_view",
|
|
516
|
-
presentation: k.presentation,
|
|
517
|
-
movedFrom: k.movedFrom
|
|
518
|
-
};
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
// src/viewLook.ts
|
|
522
|
-
function lookFromDocument(doc) {
|
|
523
|
-
const data = doc ?? {};
|
|
524
|
-
const read = viewSettings(data);
|
|
525
|
-
const out = {};
|
|
526
|
-
const has = (key) => Object.prototype.hasOwnProperty.call(data, key);
|
|
527
|
-
if (has("layout") && VIEW_LAYOUTS.includes(String(data["layout"]))) {
|
|
528
|
-
out.layout = data["layout"];
|
|
529
|
-
}
|
|
530
|
-
if (has("group_field")) out.groupField = read.groupField;
|
|
531
|
-
if (has("swimlane_field")) out.swimlaneField = read.swimlaneField;
|
|
532
|
-
if (has("collapsed_columns")) out.collapsedColumns = read.collapsedColumns;
|
|
533
|
-
if (has("measure")) out.measure = read.measure;
|
|
534
|
-
if (has("date_field")) out.dateField = read.dateField;
|
|
535
|
-
if (has("start_field")) out.startField = read.startField;
|
|
536
|
-
if (has("end_field")) out.endField = read.endField;
|
|
537
|
-
if (has("image_field")) out.imageField = read.imageField;
|
|
538
|
-
if (has("sorts")) out.sorts = read.sorts;
|
|
539
|
-
if (has("where")) out.where = read.where;
|
|
540
|
-
if (has("presentation")) out.presentation = parseGridPresentation(data["presentation"]);
|
|
541
|
-
return out;
|
|
542
|
-
}
|
|
543
|
-
function applyLook(view, look) {
|
|
544
|
-
if (!look) return view;
|
|
545
|
-
return { ...view, ...look };
|
|
546
|
-
}
|
|
547
|
-
async function readLooks(client, tableId) {
|
|
548
|
-
const answered = await client.viewLookRead({ table_id: tableId });
|
|
549
|
-
if (!answered.ok) return answered;
|
|
550
|
-
const out = {};
|
|
551
|
-
for (const [viewId, row] of Object.entries(answered.data ?? {})) {
|
|
552
|
-
out[viewId] = lookFromDocument(row?.look ?? null);
|
|
553
|
-
}
|
|
554
|
-
return { ok: true, data: out };
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
// src/entityQuery.ts
|
|
558
|
-
function entityTableQuery(options = {}) {
|
|
559
|
-
const search = (options.search ?? "").trim();
|
|
560
|
-
return { ...options.pageSize ? { pageSize: options.pageSize } : {}, ...search ? { search } : {} };
|
|
561
|
-
}
|
|
562
|
-
function entityChartQuestion(input) {
|
|
563
|
-
const m = input.measure ?? { op: "count" };
|
|
564
|
-
return {
|
|
565
|
-
...input.by ? { by: [input.by] } : {},
|
|
566
|
-
show: [m.op === "count" ? "count" : { op: m.op, of: m.of }],
|
|
567
|
-
...input.where ? { where: input.where } : {},
|
|
568
|
-
...input.organization ? { organization: input.organization } : {}
|
|
569
|
-
};
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
// src/firstPageEntity.ts
|
|
573
|
-
function recordedClient(input) {
|
|
574
|
-
const recording = recordingDataSource(asRecordsDataSource(input.dataSource));
|
|
575
|
-
const client = createRecordsClient({ dataSource: recording.source, organizationId: input.organizationId, actor: input.actor, onError: () => {
|
|
576
|
-
} });
|
|
577
|
-
return { recording, client };
|
|
578
|
-
}
|
|
579
|
-
function mergeSeeds(...seeds) {
|
|
580
|
-
const held = seeds.filter((s) => Boolean(s));
|
|
581
|
-
const answers = /* @__PURE__ */ new Map();
|
|
582
|
-
for (const seed of held) for (const a of seed.answers) answers.set(`${a.door}|${JSON.stringify(a.args)}`, a);
|
|
583
|
-
return { at: held.length ? Math.min(...held.map((s) => s.at)) : Date.now(), answers: [...answers.values()] };
|
|
584
|
-
}
|
|
585
|
-
async function askEntityBlockSeed(input) {
|
|
586
|
-
const recording = recordingDataSource(asRecordsDataSource(input.dataSource));
|
|
587
|
-
const port = createSeedPort(recording.source);
|
|
588
|
-
try {
|
|
589
|
-
await Promise.all([port.describe(input.token), port.list(input.token, entityTableQuery(input.question ?? {}))]);
|
|
590
|
-
} catch {
|
|
591
|
-
}
|
|
592
|
-
return recording.seed();
|
|
593
|
-
}
|
|
594
|
-
async function askChartSeed(input) {
|
|
595
|
-
const { recording, client } = recordedClient(input);
|
|
596
|
-
try {
|
|
597
|
-
await client.drillAsk({ source: input.source, question: entityChartQuestion(input.question ?? {}) });
|
|
598
|
-
} catch {
|
|
599
|
-
}
|
|
600
|
-
return recording.seed();
|
|
601
|
-
}
|
|
602
|
-
async function askTileSeed(input) {
|
|
603
|
-
const { recording, client } = recordedClient(input);
|
|
604
|
-
const specs = Array.isArray(input.spec) ? input.spec : [input.spec];
|
|
605
|
-
await Promise.all(specs.map((spec) => client.recordAggregate({ table_id: input.tableId, ...spec }).catch(() => null)));
|
|
606
|
-
return recording.seed();
|
|
180
|
+
function presentationDocument(p) {
|
|
181
|
+
return presentationIsEmpty(p) ? "" : JSON.stringify(p);
|
|
607
182
|
}
|
|
183
|
+
var gridPresentationCodec = {
|
|
184
|
+
parse: parseGridPresentation,
|
|
185
|
+
isEmpty: presentationIsEmpty,
|
|
186
|
+
toDocument: (presentation) => JSON.parse(presentationDocument(presentation))
|
|
187
|
+
};
|
|
188
|
+
var boundViews = base.bindViewCodec(gridPresentationCodec);
|
|
189
|
+
var { viewSettings, viewSettingsPatch } = boundViews;
|
|
608
190
|
|
|
609
191
|
// src/firstPage.ts
|
|
610
|
-
var
|
|
611
|
-
var EMBEDDED_PAGE_SIZE = 50;
|
|
612
|
-
function viewFilterOf(shown, fields) {
|
|
613
|
-
if (!shown) return void 0;
|
|
614
|
-
const base = shown.where ?? (shown.filters && Object.keys(shown.filters).length > 0 ? shown.filters : void 0);
|
|
615
|
-
return storeQuestion(fields, base, {}).filter;
|
|
616
|
-
}
|
|
617
|
-
function firstGridPageArgs(input) {
|
|
618
|
-
const { shown, fields } = input;
|
|
619
|
-
if (!shown) return null;
|
|
620
|
-
if ((shown.layout ?? "grid") !== "grid") return null;
|
|
621
|
-
if (shown.ruleId) return null;
|
|
622
|
-
if (shown.order === "manual") return null;
|
|
623
|
-
const grouping = shown.presentation?.grouping;
|
|
624
|
-
if (grouping && !(input.merged && isPlainGrouping(grouping))) return null;
|
|
625
|
-
const first = (shown.sorts ?? [])[0];
|
|
626
|
-
const viewSort = first && fields.some((f) => f.key === first.field) ? { id: first.field, direction: first.direction } : null;
|
|
627
|
-
const opening = viewSort ?? defaultSortOf(input.table, fields);
|
|
628
|
-
return {
|
|
629
|
-
p_table_id: input.tableId,
|
|
630
|
-
p_filter: viewFilterOf(shown, fields) ?? {},
|
|
631
|
-
p_search: null,
|
|
632
|
-
p_sort: groupedPageSort(fields, grouping?.field ?? null, pageSortFor(fields, opening)),
|
|
633
|
-
p_view_id: null,
|
|
634
|
-
p_limit: input.pageSize ?? TABLE_PAGE_SIZE,
|
|
635
|
-
p_offset: 0
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
async function firstGridPageRequest(client, tableId, options = {}) {
|
|
639
|
-
return (await firstGridOpening(client, tableId, options))?.args ?? null;
|
|
640
|
-
}
|
|
641
|
-
function defaultSpec(tableId) {
|
|
642
|
-
return { name: "All", subject: tableId, layout: "grid", isDefault: true };
|
|
643
|
-
}
|
|
644
|
-
function shownFromSpec(spec, tableId) {
|
|
645
|
-
return { ...spec, subject: spec.subject ?? tableId, id: "", movedFrom: null };
|
|
646
|
-
}
|
|
647
|
-
async function firstGridOpening(client, tableId, options) {
|
|
648
|
-
const explicit = options.view;
|
|
649
|
-
const [table, fields, views, looks] = await Promise.all([
|
|
650
|
-
client.tableRead({ table_id: tableId }),
|
|
651
|
-
client.fields({ table_id: tableId }),
|
|
652
|
-
explicit ? Promise.resolve(null) : client.views({ table_id: tableId }),
|
|
653
|
-
explicit ? Promise.resolve(null) : readLooks(client, tableId)
|
|
654
|
-
]);
|
|
655
|
-
if (!table.ok || !fields.ok) return null;
|
|
656
|
-
let shown;
|
|
657
|
-
if (explicit) {
|
|
658
|
-
shown = shownFromSpec(explicit, tableId);
|
|
659
|
-
} else {
|
|
660
|
-
if (!views?.ok || !looks?.ok) return null;
|
|
661
|
-
const mine = views.data.map(viewFromRow).filter((v) => v.subject === tableId);
|
|
662
|
-
const view = defaultViewOf(mine) ?? mine[0] ?? null;
|
|
663
|
-
shown = view ? applyLook(view, looks.data[view.id]) : shownFromSpec(defaultSpec(tableId), tableId);
|
|
664
|
-
}
|
|
665
|
-
const args = firstGridPageArgs({
|
|
666
|
-
tableId,
|
|
667
|
-
table: table.data,
|
|
668
|
-
fields: fields.data,
|
|
669
|
-
shown,
|
|
670
|
-
...options.pageSize ? { pageSize: options.pageSize } : {},
|
|
671
|
-
...options.merged ? { merged: true } : {}
|
|
672
|
-
});
|
|
673
|
-
return args ? { args, shown, fields: fields.data } : null;
|
|
674
|
-
}
|
|
675
|
-
function serverRowsOf(seed) {
|
|
676
|
-
const found = seed?.answers.find((a) => a.door === "server_rows");
|
|
677
|
-
const data = found?.data;
|
|
678
|
-
if (!data || typeof data !== "object") return null;
|
|
679
|
-
return { on: data.on === true, capMs: typeof data.cap_ms === "number" && data.cap_ms > 0 ? data.cap_ms : null };
|
|
680
|
-
}
|
|
681
|
-
async function askTablePageSeed(input) {
|
|
682
|
-
const recording = recordingDataSource(asRecordsDataSource(input.dataSource));
|
|
683
|
-
const client = createRecordsClient({
|
|
684
|
-
dataSource: recording.source,
|
|
685
|
-
organizationId: input.organizationId,
|
|
686
|
-
actor: input.actor,
|
|
687
|
-
onError: () => {
|
|
688
|
-
}
|
|
689
|
-
});
|
|
690
|
-
const record = input.recordId ? Promise.resolve(
|
|
691
|
-
recording.source.rpc("record_page_bundle", { p_organization_id: input.organizationId, p_record_id: input.recordId }, { schema: "custom" })
|
|
692
|
-
).catch(() => null) : null;
|
|
693
|
-
try {
|
|
694
|
-
const pageSize = input.pageSize ?? (input.embedded ? EMBEDDED_PAGE_SIZE : TABLE_PAGE_SIZE);
|
|
695
|
-
const opening = await firstGridOpening(client, input.tableId, { pageSize, ...input.merged ? { merged: true } : {}, ...input.view ? { view: input.view } : {} });
|
|
696
|
-
const wantRows = typeof input.rows === "function" ? input.rows(recording.seed()) : input.rows !== false;
|
|
697
|
-
if (opening && wantRows) {
|
|
698
|
-
const { args, shown, fields } = opening;
|
|
699
|
-
const page = await client.listPage({
|
|
700
|
-
table_id: args.p_table_id,
|
|
701
|
-
filter: args.p_filter,
|
|
702
|
-
search: args.p_search,
|
|
703
|
-
sort: args.p_sort,
|
|
704
|
-
view_id: args.p_view_id,
|
|
705
|
-
limit: args.p_limit,
|
|
706
|
-
offset: args.p_offset
|
|
707
|
-
});
|
|
708
|
-
if (page.ok) {
|
|
709
|
-
const chosen = shown?.presentation?.summaries ?? {};
|
|
710
|
-
const groupKey = shown?.presentation?.grouping?.field ?? null;
|
|
711
|
-
const reads = [];
|
|
712
|
-
const filter = args.p_filter && Object.keys(args.p_filter).length > 0 ? args.p_filter : void 0;
|
|
713
|
-
if (groupKey) {
|
|
714
|
-
reads.push(client.recordAggregate({ table_id: input.tableId, groupBy: [groupKey], measures: groupFactMeasures(chosen), limit: 1e3, ...filter ? { filter } : {} }));
|
|
715
|
-
}
|
|
716
|
-
const bar = summaryBarMeasures(chosen);
|
|
717
|
-
if (bar.length > 0) reads.push(client.recordAggregate({ table_id: input.tableId, measures: bar, ...filter ? { filter } : {} }));
|
|
718
|
-
for (const field2 of fields) {
|
|
719
|
-
if (field2.type !== "list" && field2.type !== "relation") continue;
|
|
720
|
-
const ids = /* @__PURE__ */ new Set();
|
|
721
|
-
for (const row of page.data.rows) {
|
|
722
|
-
const value = row.document?.[field2.key];
|
|
723
|
-
for (const id of Array.isArray(value) ? value.map(String) : typeof value === "string" ? [value] : []) if (isUuidShape(id)) ids.add(id);
|
|
724
|
-
}
|
|
725
|
-
if (ids.size > 0) reads.push(client.relationWordsMany({ field_id: field2.id, record_ids: [...ids] }));
|
|
726
|
-
}
|
|
727
|
-
if (input.merged) {
|
|
728
|
-
for (const key of choiceFieldKeys(fields)) {
|
|
729
|
-
reads.push(client.recordAggregate({ table_id: input.tableId, groupBy: [key], measures: [{ op: "count" }], limit: 500, ...filter ? { filter } : {} }));
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
const unversioned = page.data.rows.filter((row) => ownVersion(row) === null).map((row) => row.id);
|
|
733
|
-
if (unversioned.length > 0) reads.push(client.recordHeaders({ ids: unversioned }));
|
|
734
|
-
reads.push(
|
|
735
|
-
client.reverseColumns({ table_id: input.tableId }).then(async (columns) => {
|
|
736
|
-
if (!columns.ok || columns.data.length === 0) return null;
|
|
737
|
-
const record_ids = page.data.rows.map((row) => row.id);
|
|
738
|
-
const all = await client.reverseLinksFields({ table_id: input.tableId, source_field_ids: columns.data.map((c) => c.source_field_id), record_ids, limit: REVERSE_CELL_CHIPS });
|
|
739
|
-
if (all.ok || all.error.code !== "door_absent") return null;
|
|
740
|
-
return Promise.all(columns.data.map((c) => client.reverseLinksMany({ table_id: input.tableId, source_field_id: c.source_field_id, record_ids, limit: REVERSE_CELL_CHIPS })));
|
|
741
|
-
})
|
|
742
|
-
);
|
|
743
|
-
await Promise.all(reads.map((read) => read.catch(() => null)));
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
} catch {
|
|
747
|
-
}
|
|
748
|
-
if (record) await record;
|
|
749
|
-
return recording.seed();
|
|
750
|
-
}
|
|
192
|
+
var { firstGridPageRequest, askTablePageSeed } = bindFirstPageCodec(gridPresentationCodec);
|
|
751
193
|
|
|
752
|
-
export {
|
|
194
|
+
export { askTablePageSeed, firstGridPageRequest };
|
|
753
195
|
//# sourceMappingURL=first-page.js.map
|
|
754
196
|
//# sourceMappingURL=first-page.js.map
|