@ai-matrx/records-ui 0.113.31 → 0.113.33
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 +38 -12
- package/dist/first-page.cjs +59 -602
- 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 +25 -594
- package/dist/first-page.js.map +1 -1
- package/dist/index.cjs +447 -1299
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -537
- package/dist/index.d.ts +34 -537
- package/dist/index.js +361 -1162
- package/dist/index.js.map +1 -1
- package/dist/pickers.cjs +237 -237
- package/dist/pickers.cjs.map +1 -1
- package/dist/pickers.js +116 -116
- package/dist/pickers.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -81,12 +81,12 @@ function whatYouMayDo(level, known = true) {
|
|
|
81
81
|
var NOT_ANSWERED_YET = whatYouMayDo(null, false);
|
|
82
82
|
var KERNEL_REASON = "This is one of the tables the platform ships, so its columns are not changed from a screen. Make your own table to change columns.";
|
|
83
83
|
function whatYouMayDoWithTable(table, level, known) {
|
|
84
|
-
const
|
|
85
|
-
if (!table?.is_kernel) return
|
|
84
|
+
const base2 = whatYouMayDo(level, known);
|
|
85
|
+
if (!table?.is_kernel) return base2;
|
|
86
86
|
return {
|
|
87
|
-
...
|
|
87
|
+
...base2,
|
|
88
88
|
structure: false,
|
|
89
|
-
why: (what) => what === "structure" ? KERNEL_REASON :
|
|
89
|
+
why: (what) => what === "structure" ? KERNEL_REASON : base2.why(what)
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -215,8 +215,8 @@ var UNREAD_RECORD_LABEL = "Couldn't load this name";
|
|
|
215
215
|
function realPlural(table) {
|
|
216
216
|
const plural4 = (table.label_plural ?? "").trim();
|
|
217
217
|
if (plural4 === "") return null;
|
|
218
|
-
for (const
|
|
219
|
-
const b = (
|
|
218
|
+
for (const base2 of [table.name, table.label_singular]) {
|
|
219
|
+
const b = (base2 ?? "").trim();
|
|
220
220
|
if (b !== "" && plural4 === `${b}s`) return null;
|
|
221
221
|
}
|
|
222
222
|
return plural4;
|
|
@@ -516,7 +516,7 @@ async function rowActionFromAgent(input, fields, check) {
|
|
|
516
516
|
const name = input["name"];
|
|
517
517
|
if (typeof name !== "string" || !name.trim()) throw new Error(`editing_row_action.name must be the button's label \u2014 received ${describeValue(name)}.`);
|
|
518
518
|
const kind = input["kind"];
|
|
519
|
-
const
|
|
519
|
+
const base2 = {
|
|
520
520
|
name: name.trim(),
|
|
521
521
|
kind: kind === "agent" ? "agent" : "update",
|
|
522
522
|
confirm: input["confirm"] === true,
|
|
@@ -526,14 +526,14 @@ async function rowActionFromAgent(input, fields, check) {
|
|
|
526
526
|
if (kind === "agent") {
|
|
527
527
|
const prompt = input["prompt"];
|
|
528
528
|
if (typeof prompt !== "string" || !prompt.trim()) throw new Error(`An agent action needs \`prompt\`: what the agent does with the row \u2014 received ${describeValue(prompt)}.`);
|
|
529
|
-
return { ...
|
|
529
|
+
return { ...base2, prompt: prompt.trim() };
|
|
530
530
|
}
|
|
531
531
|
if (kind !== "update") throw new Error(`editing_row_action.kind must be "update" or "agent" \u2014 received ${describeValue(kind)}.`);
|
|
532
532
|
const steps = input["steps"];
|
|
533
533
|
if (!Array.isArray(steps) || steps.length === 0) throw new Error(`An update action needs \`steps\`: a non-empty array \u2014 received ${describeValue(steps)}.`);
|
|
534
534
|
const made = [];
|
|
535
535
|
for (let i = 0; i < steps.length; i += 1) made.push(await stepFromAgent(steps[i], i, fields, check));
|
|
536
|
-
return { ...
|
|
536
|
+
return { ...base2, steps: made };
|
|
537
537
|
}
|
|
538
538
|
function actionForAgent(action3, fields) {
|
|
539
539
|
const key = (id) => fields.find((f) => f.id === id)?.key ?? id;
|
|
@@ -949,6 +949,9 @@ function fieldTypeLabel(field2) {
|
|
|
949
949
|
}
|
|
950
950
|
|
|
951
951
|
// src/gridPage.ts
|
|
952
|
+
import { holdsNumbers } from "@ai-matrx/records/first-page";
|
|
953
|
+
import { holdsNumbers as holdsNumbers2, pageSortFor, sortAsFor } from "@ai-matrx/records/first-page";
|
|
954
|
+
import { containsPattern } from "@ai-matrx/records/data";
|
|
952
955
|
function sortRefusal(f) {
|
|
953
956
|
if (!computedOnRead(f)) return null;
|
|
954
957
|
return `${fieldName(f)} is worked out each time it is read, so the store keeps no value to sort the whole table by. Sort by a column it is worked out from.`;
|
|
@@ -961,26 +964,6 @@ function computedOnRead(f) {
|
|
|
961
964
|
const kind = String(editorKindFor(f));
|
|
962
965
|
return (f.type === "formula" || kind === "formula" || kind === "lookup" || kind === "rollup") && String(f.compute_on ?? "read") === "read";
|
|
963
966
|
}
|
|
964
|
-
function holdsNumbers(field2) {
|
|
965
|
-
const kind = String(editorKindFor(field2));
|
|
966
|
-
if (kind === "number" || kind === "currency" || kind === "percent") return true;
|
|
967
|
-
return String((field2.config ?? {})["system"] ?? "") === "autonumber";
|
|
968
|
-
}
|
|
969
|
-
function sortAsFor(field2) {
|
|
970
|
-
const kind = String(editorKindFor(field2));
|
|
971
|
-
if (holdsNumbers(field2)) return "number";
|
|
972
|
-
if (kind === "datetime") return "date";
|
|
973
|
-
return "text";
|
|
974
|
-
}
|
|
975
|
-
function pageSortFor(fields, sort) {
|
|
976
|
-
if (!sort) return [];
|
|
977
|
-
const field2 = fields.find((f) => f.key === sort.id);
|
|
978
|
-
if (!field2) return [];
|
|
979
|
-
return [{ field: field2.key, direction: sort.direction === "desc" ? "desc" : "asc", as: sortAsFor(field2) }];
|
|
980
|
-
}
|
|
981
|
-
function containsPattern(text) {
|
|
982
|
-
return `(?i)${text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`;
|
|
983
|
-
}
|
|
984
967
|
var BLANK_VALUE = "__empty__";
|
|
985
968
|
var field = (f) => ({ field: f.id });
|
|
986
969
|
var constant = (value) => ({ const: value });
|
|
@@ -1076,12 +1059,12 @@ function dayWindow(day, holdsDays) {
|
|
|
1076
1059
|
const ymd = (t) => `${t.getUTCFullYear()}-${String(t.getUTCMonth() + 1).padStart(2, "0")}-${String(t.getUTCDate()).padStart(2, "0")}`;
|
|
1077
1060
|
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))) };
|
|
1078
1061
|
}
|
|
1079
|
-
function storeQuestion(fields,
|
|
1062
|
+
function storeQuestion(fields, base2, columnFilters, now = /* @__PURE__ */ new Date()) {
|
|
1080
1063
|
const refused = [];
|
|
1081
1064
|
const flat = {};
|
|
1082
1065
|
const rules = [];
|
|
1083
|
-
if (
|
|
1084
|
-
else if (
|
|
1066
|
+
if (base2 && isRuleFilter(base2)) rules.push(base2);
|
|
1067
|
+
else if (base2) Object.assign(flat, base2);
|
|
1085
1068
|
for (const [key, value] of Object.entries(columnFilters)) {
|
|
1086
1069
|
if (!value) continue;
|
|
1087
1070
|
const f = fields.find((candidate) => candidate.key === key);
|
|
@@ -1622,32 +1605,7 @@ function useLabelWait(field2) {
|
|
|
1622
1605
|
}
|
|
1623
1606
|
|
|
1624
1607
|
// src/gridLook.ts
|
|
1625
|
-
|
|
1626
|
-
const raw = table?.default_sort ?? null;
|
|
1627
|
-
const first = Array.isArray(raw) ? raw[0] : raw;
|
|
1628
|
-
let name = null;
|
|
1629
|
-
let direction = "asc";
|
|
1630
|
-
if (typeof first === "string") {
|
|
1631
|
-
const trimmed = first.trim();
|
|
1632
|
-
if (trimmed === "") return null;
|
|
1633
|
-
if (trimmed.startsWith("-")) {
|
|
1634
|
-
name = trimmed.slice(1).trim();
|
|
1635
|
-
direction = "desc";
|
|
1636
|
-
} else {
|
|
1637
|
-
const [head, tail] = trimmed.split(/\s+/);
|
|
1638
|
-
name = head ?? null;
|
|
1639
|
-
if (tail && tail.toLowerCase() === "desc") direction = "desc";
|
|
1640
|
-
}
|
|
1641
|
-
} else if (first && typeof first === "object") {
|
|
1642
|
-
const entry = first;
|
|
1643
|
-
const named = entry["field"] ?? entry["key"] ?? entry["id"];
|
|
1644
|
-
name = typeof named === "string" ? named : null;
|
|
1645
|
-
if (String(entry["direction"] ?? "").toLowerCase() === "desc") direction = "desc";
|
|
1646
|
-
}
|
|
1647
|
-
if (!name) return null;
|
|
1648
|
-
const field2 = fields.find((f) => f.key === name) ?? fields.find((f) => f.id === name);
|
|
1649
|
-
return field2 ? { id: field2.key, direction } : null;
|
|
1650
|
-
}
|
|
1608
|
+
import { defaultSortOf } from "@ai-matrx/records/first-page";
|
|
1651
1609
|
var ROW_HEIGHT_PX = {
|
|
1652
1610
|
compact: 28,
|
|
1653
1611
|
normal: void 0,
|
|
@@ -2005,7 +1963,7 @@ function FieldRetype({ field: field2, tableId, onRetyped }) {
|
|
|
2005
1963
|
const [to, setTo] = useState4(null);
|
|
2006
1964
|
const [preview, setPreview] = useState4(null);
|
|
2007
1965
|
const [asking, setAsking] = useState4(false);
|
|
2008
|
-
const [
|
|
1966
|
+
const [refusal3, setRefusal] = useState4(null);
|
|
2009
1967
|
const [busy, setBusy] = useState4(false);
|
|
2010
1968
|
const [said2, setSaid] = useState4(null);
|
|
2011
1969
|
const name = fieldName(field2);
|
|
@@ -2103,7 +2061,7 @@ function FieldRetype({ field: field2, tableId, onRetyped }) {
|
|
|
2103
2061
|
preview.keptAside > 0 ? `; ${preview.keptAside} ${preview.keptAside === 1 ? "value does" : "values do"} not fit and will be kept aside with ${preview.keptAside === 1 ? "its record" : "their records"}, with the reason \u2014 nothing is deleted` + (preview.examples.length > 0 ? ` (for example ${preview.examples.map((e) => `\u201C${e}\u201D`).join(", ")})` : "") : "",
|
|
2104
2062
|
preview.partial ? ". Counted over the first 1,000 different values." : "."
|
|
2105
2063
|
] }) : null,
|
|
2106
|
-
|
|
2064
|
+
refusal3 ? /* @__PURE__ */ jsx6(RefusalNotice, { error: refusal3 }) : null,
|
|
2107
2065
|
said2 ? /* @__PURE__ */ jsx6("p", { role: "status", className: "text-[11px] text-muted-foreground", "data-records-retype-done": "", children: said2 }) : null
|
|
2108
2066
|
] });
|
|
2109
2067
|
}
|
|
@@ -2879,10 +2837,10 @@ function TableDetails({
|
|
|
2879
2837
|
if (slots.details.current === slot) slots.details.current = null;
|
|
2880
2838
|
};
|
|
2881
2839
|
}, [slots]);
|
|
2882
|
-
const write = async (patch,
|
|
2840
|
+
const write = async (patch, base2) => {
|
|
2883
2841
|
setBusy(true);
|
|
2884
2842
|
setRefused(null);
|
|
2885
|
-
const written = await (0, writeOnTheWinningVersion_exports.updateOnTheWinningVersion)(client, tableId, patch, await (0, recordVersions_exports.readTableVersionNow)(client, tableId),
|
|
2843
|
+
const written = await (0, writeOnTheWinningVersion_exports.updateOnTheWinningVersion)(client, tableId, patch, await (0, recordVersions_exports.readTableVersionNow)(client, tableId), base2);
|
|
2886
2844
|
setBusy(false);
|
|
2887
2845
|
if (!written.ok) {
|
|
2888
2846
|
setRefused(refusalSentence(written.error));
|
|
@@ -3981,13 +3939,13 @@ function styleFromDecorations(decorations, fields) {
|
|
|
3981
3939
|
return style;
|
|
3982
3940
|
}
|
|
3983
3941
|
function resolveTableStyle(decorations, fields, viewStyle) {
|
|
3984
|
-
const
|
|
3985
|
-
if (!viewStyle) return
|
|
3986
|
-
const colorBy = viewStyle.colorBy ??
|
|
3987
|
-
const rules = viewStyle.rules ??
|
|
3988
|
-
const rows = viewStyle.rows ??
|
|
3989
|
-
const columns = viewStyle.columns ??
|
|
3990
|
-
const cells = viewStyle.cells ??
|
|
3942
|
+
const base2 = styleFromDecorations(decorations, fields);
|
|
3943
|
+
if (!viewStyle) return base2;
|
|
3944
|
+
const colorBy = viewStyle.colorBy ?? base2.colorBy;
|
|
3945
|
+
const rules = viewStyle.rules ?? base2.rules;
|
|
3946
|
+
const rows = viewStyle.rows ?? base2.rows;
|
|
3947
|
+
const columns = viewStyle.columns ?? base2.columns;
|
|
3948
|
+
const cells = viewStyle.cells ?? base2.cells;
|
|
3991
3949
|
return {
|
|
3992
3950
|
version: 1,
|
|
3993
3951
|
...colorBy !== void 0 ? { colorBy } : {},
|
|
@@ -4406,7 +4364,7 @@ function RelationPicker({ field: field2, value, onChange, disabled, id, classNam
|
|
|
4406
4364
|
const client = useOptionalRecordsClient3();
|
|
4407
4365
|
const [rows, setRows] = useState12(null);
|
|
4408
4366
|
const [words2, setWords] = useState12({});
|
|
4409
|
-
const [
|
|
4367
|
+
const [refusal3, setRefusal] = useState12(null);
|
|
4410
4368
|
const [search, setSearch] = useState12("");
|
|
4411
4369
|
const [open, setOpenState] = useState12(autoOpen === true);
|
|
4412
4370
|
const onCloseRef = useRef7(onClose);
|
|
@@ -4590,8 +4548,8 @@ function RelationPicker({ field: field2, value, onChange, disabled, id, classNam
|
|
|
4590
4548
|
})),
|
|
4591
4549
|
onPick: toggle,
|
|
4592
4550
|
notice: /* @__PURE__ */ jsxs13(Fragment4, { children: [
|
|
4593
|
-
|
|
4594
|
-
!rows && !
|
|
4551
|
+
refusal3 ? /* @__PURE__ */ jsx15(RefusalLine, { error: refusal3, className: "p-2" }) : null,
|
|
4552
|
+
!rows && !refusal3 ? /* @__PURE__ */ jsx15("p", { className: "p-2 text-xs text-muted-foreground", children: "Reading\u2026" }) : null,
|
|
4595
4553
|
full ? /* @__PURE__ */ jsxs13("p", { className: "p-2 text-xs text-muted-foreground", children: [
|
|
4596
4554
|
fieldName(field2),
|
|
4597
4555
|
" can point at ",
|
|
@@ -5029,500 +4987,35 @@ import { Badge as Badge5, cn as cn19 } from "@ai-matrx/design-system";
|
|
|
5029
4987
|
import { createContext as createContext4, useContext as useContext4 } from "react";
|
|
5030
4988
|
|
|
5031
4989
|
// src/firstPage.ts
|
|
5032
|
-
import {
|
|
5033
|
-
import { isUuidShape as isUuidShape3 } from "@ai-matrx/kit/uuid";
|
|
5034
|
-
|
|
5035
|
-
// src/groupReads.ts
|
|
5036
|
-
function groupedPageSort(fields, groupKey, sort) {
|
|
5037
|
-
if (!groupKey) return sort;
|
|
5038
|
-
const field2 = fields.find((f) => f.key === groupKey);
|
|
5039
|
-
if (!field2) return sort;
|
|
5040
|
-
return [{ field: groupKey, direction: "asc", as: sortAsFor(field2) }, ...sort.filter((s) => s.field !== groupKey)];
|
|
5041
|
-
}
|
|
5042
|
-
function chosenEntries(chosen) {
|
|
5043
|
-
return JSON.parse(JSON.stringify(Object.entries(chosen).sort())).filter(([, op2]) => op2 in MEASURE_LABEL);
|
|
5044
|
-
}
|
|
5045
|
-
function groupFactMeasures(chosen) {
|
|
5046
|
-
return [{ op: "count" }, ...chosenEntries(chosen).filter(([, op2]) => op2 !== "count").map(([key, op2]) => ({ op: op2, key }))];
|
|
5047
|
-
}
|
|
5048
|
-
var REVERSE_CELL_CHIPS = 3;
|
|
4990
|
+
import { bindFirstPageCodec } from "@ai-matrx/records/first-page";
|
|
5049
4991
|
|
|
5050
4992
|
// src/viewKeys.ts
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
...STORE_KEEPS_TIMELINE ? [
|
|
5065
|
-
{ path: "start_field", shape: "field:date", layouts: ["timeline"], writer: "caller" },
|
|
5066
|
-
{ path: "end_field", shape: "field:date", layouts: ["calendar", "timeline"], writer: "caller" }
|
|
5067
|
-
] : [],
|
|
5068
|
-
{ path: "image_field", shape: "field", layouts: ["gallery"], writer: "caller" },
|
|
5069
|
-
{ path: "sorts", shape: "sorts", layouts: ALL, writer: "caller" },
|
|
5070
|
-
{ path: "rule_id", shape: "uuid", layouts: ALL, writer: "caller" },
|
|
5071
|
-
{ path: "is_default", shape: "boolean", layouts: ALL, writer: "caller" },
|
|
5072
|
-
{ path: "presentation", shape: "presentation", layouts: ALL, writer: "caller" },
|
|
5073
|
-
{ path: "presentation.style", shape: "style", layouts: ALL, writer: "caller" },
|
|
5074
|
-
{ path: "presentation.formats", shape: "object", layouts: GRIDS, writer: "caller" },
|
|
5075
|
-
{ path: "presentation.frozen", shape: "fields", layouts: GRIDS, writer: "caller" },
|
|
5076
|
-
{ path: "presentation.grouping", shape: "grouping", layouts: ["grid", "gallery", "list"], writer: "caller" },
|
|
5077
|
-
{ path: "presentation.widths", shape: "widths", layouts: GRIDS, writer: "caller" },
|
|
5078
|
-
{ path: "presentation.rowHeight", shape: "row_height", layouts: GRIDS, writer: "caller" },
|
|
5079
|
-
{ path: "presentation.hiddenFields", shape: "fields", layouts: HIDES, writer: "caller" },
|
|
5080
|
-
{ path: "presentation.cardHidden", shape: "fields", layouts: ["kanban", "calendar", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list", "gallery"], writer: "caller" },
|
|
5081
|
-
{ path: "presentation.columnOrder", shape: "fields", layouts: GRIDS, writer: "caller" },
|
|
5082
|
-
{ path: "presentation.gallerySize", shape: "gallery_size", layouts: ["gallery"], writer: "caller" },
|
|
5083
|
-
{ path: "presentation.wrap", shape: "boolean", layouts: GRIDS, writer: "caller" },
|
|
5084
|
-
{ path: "presentation.wrapColumns", shape: "fields", layouts: GRIDS, writer: "caller" },
|
|
5085
|
-
{ path: "presentation.fit", shape: "fit", layouts: GRIDS, writer: "caller" },
|
|
5086
|
-
{ path: "presentation.freezeFirst", shape: "boolean", layouts: GRIDS, writer: "caller" },
|
|
5087
|
-
{ path: "presentation.footer", shape: "footer", layouts: GRIDS, writer: "caller" },
|
|
5088
|
-
{ path: "presentation.summaries", shape: "summaries", layouts: GRIDS, writer: "caller" },
|
|
5089
|
-
{ path: "grid", shape: "grid", layouts: GRIDS, writer: "caller" },
|
|
5090
|
-
{ path: "hidden_fields", shape: "input", layouts: HIDES, writer: "input" },
|
|
5091
|
-
{ path: "table_id", shape: "server", layouts: ALL, writer: "server" },
|
|
5092
|
-
{ path: "order", shape: "server", layouts: GRIDS, writer: "server" },
|
|
5093
|
-
{ path: "moved_from", shape: "server", layouts: ALL, writer: "server" }
|
|
5094
|
-
];
|
|
5095
|
-
var STORE_KEPT_LAYOUTS = ["grid", "kanban", "calendar", "gallery", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
|
|
5096
|
-
function storeKeepsLayout(layout) {
|
|
5097
|
-
return STORE_KEPT_LAYOUTS.includes(layout);
|
|
5098
|
-
}
|
|
5099
|
-
function viewKeysFor(layout) {
|
|
5100
|
-
return VIEW_KEYS.filter((k) => k.layouts.includes(layout)).map((k) => k.path);
|
|
5101
|
-
}
|
|
5102
|
-
var KINDS = STORE_KEPT_LAYOUTS;
|
|
5103
|
-
function viewSettings(definition, rowFilters) {
|
|
5104
|
-
const data = definition ?? {};
|
|
5105
|
-
const text = (key) => {
|
|
5106
|
-
const v = data[key];
|
|
5107
|
-
return typeof v === "string" && v !== "" ? v : null;
|
|
5108
|
-
};
|
|
5109
|
-
const layout = String(data["layout"] ?? "grid");
|
|
5110
|
-
const flat = rowFilters ?? (isObject2(data["filters"]) ? data["filters"] : null);
|
|
5111
|
-
const moved = data["moved_from"];
|
|
5112
|
-
return {
|
|
5113
|
-
layout: KINDS.includes(layout) ? layout : "grid",
|
|
5114
|
-
filters: flat && Object.keys(flat).length > 0 ? flat : null,
|
|
5115
|
-
where: isRule(data["where"]) ? data["where"] : null,
|
|
5116
|
-
groupField: text("group_field"),
|
|
5117
|
-
swimlaneField: text("swimlane_field"),
|
|
5118
|
-
collapsedColumns: Array.isArray(data["collapsed_columns"]) ? data["collapsed_columns"].filter((v) => ["string", "number", "boolean"].includes(typeof v)).map(String) : [],
|
|
5119
|
-
measure: text("measure"),
|
|
5120
|
-
dateField: text("date_field"),
|
|
5121
|
-
startField: text("start_field"),
|
|
5122
|
-
endField: text("end_field"),
|
|
5123
|
-
imageField: text("image_field"),
|
|
5124
|
-
sorts: parseSorts(data["sorts"]),
|
|
5125
|
-
ruleId: text("rule_id"),
|
|
5126
|
-
isDefault: data["is_default"] === true || data["is_default"] === "true",
|
|
5127
|
-
presentation: parseGridPresentation(data["presentation"]),
|
|
5128
|
-
movedFrom: isObject2(moved) ? moved : null
|
|
5129
|
-
};
|
|
5130
|
-
}
|
|
5131
|
-
function viewSettingsFor(settings, layout) {
|
|
5132
|
-
const reads = new Set(viewKeysFor(layout));
|
|
5133
|
-
const out = { layout: settings.layout };
|
|
5134
|
-
const take = (key, path) => {
|
|
5135
|
-
if (reads.has(path)) out[key] = settings[key];
|
|
5136
|
-
};
|
|
5137
|
-
take("filters", "filters");
|
|
5138
|
-
take("where", "where");
|
|
5139
|
-
take("groupField", "group_field");
|
|
5140
|
-
take("swimlaneField", "swimlane_field");
|
|
5141
|
-
take("collapsedColumns", "collapsed_columns");
|
|
5142
|
-
take("measure", "measure");
|
|
5143
|
-
take("dateField", "date_field");
|
|
5144
|
-
take("startField", "start_field");
|
|
5145
|
-
take("endField", "end_field");
|
|
5146
|
-
take("imageField", "image_field");
|
|
5147
|
-
take("sorts", "sorts");
|
|
5148
|
-
take("ruleId", "rule_id");
|
|
5149
|
-
take("isDefault", "is_default");
|
|
5150
|
-
const p = settings.presentation;
|
|
5151
|
-
const look = {};
|
|
5152
|
-
for (const [key, value] of Object.entries(p)) {
|
|
5153
|
-
if (reads.has(`presentation.${key}`)) look[key] = value;
|
|
5154
|
-
}
|
|
5155
|
-
out.presentation = look;
|
|
5156
|
-
return out;
|
|
5157
|
-
}
|
|
5158
|
-
function viewSettingsPatch(patch) {
|
|
5159
|
-
const out = {};
|
|
5160
|
-
const field2 = (key, path) => {
|
|
5161
|
-
if (patch[key] !== void 0) out[path] = patch[key] || null;
|
|
5162
|
-
};
|
|
5163
|
-
if (patch.layout !== void 0 && storeKeepsLayout(patch.layout)) out["layout"] = patch.layout;
|
|
5164
|
-
field2("groupField", "group_field");
|
|
5165
|
-
field2("swimlaneField", "swimlane_field");
|
|
5166
|
-
field2("measure", "measure");
|
|
5167
|
-
field2("dateField", "date_field");
|
|
5168
|
-
if (STORE_KEEPS_TIMELINE) {
|
|
5169
|
-
field2("startField", "start_field");
|
|
5170
|
-
field2("endField", "end_field");
|
|
5171
|
-
}
|
|
5172
|
-
field2("imageField", "image_field");
|
|
5173
|
-
field2("ruleId", "rule_id");
|
|
5174
|
-
if (patch.collapsedColumns !== void 0) out["collapsed_columns"] = patch.collapsedColumns ?? [];
|
|
5175
|
-
if (patch.sorts !== void 0) out["sorts"] = patch.sorts ?? [];
|
|
5176
|
-
if (patch.where !== void 0) out["where"] = patch.where ?? null;
|
|
5177
|
-
if (patch.isDefault !== void 0) out["is_default"] = patch.isDefault === true;
|
|
5178
|
-
if (patch.presentation !== void 0) {
|
|
5179
|
-
out["presentation"] = !patch.presentation || presentationIsEmpty(patch.presentation) ? null : JSON.parse(presentationDocument(patch.presentation));
|
|
5180
|
-
}
|
|
5181
|
-
return out;
|
|
5182
|
-
}
|
|
5183
|
-
function isObject2(raw) {
|
|
5184
|
-
return Boolean(raw) && typeof raw === "object" && !Array.isArray(raw);
|
|
5185
|
-
}
|
|
5186
|
-
function isRule(raw) {
|
|
5187
|
-
if (!isObject2(raw)) return false;
|
|
5188
|
-
const node = raw;
|
|
5189
|
-
return typeof node.op === "string" && Array.isArray(node.args);
|
|
5190
|
-
}
|
|
5191
|
-
function parseSorts(raw) {
|
|
5192
|
-
let list = raw;
|
|
5193
|
-
if (typeof raw === "string") {
|
|
5194
|
-
try {
|
|
5195
|
-
list = raw.trim() === "" ? [] : JSON.parse(raw);
|
|
5196
|
-
} catch {
|
|
5197
|
-
return [];
|
|
5198
|
-
}
|
|
5199
|
-
}
|
|
5200
|
-
if (!Array.isArray(list)) return [];
|
|
5201
|
-
return list.filter((s) => isObject2(s) && typeof s.field === "string").map((s) => ({ field: s.field, direction: s.direction === "desc" ? "desc" : "asc" }));
|
|
5202
|
-
}
|
|
5203
|
-
|
|
5204
|
-
// src/views.ts
|
|
5205
|
-
var VIEW_LAYOUTS = ["grid", "kanban", "calendar", "gallery", "timeline", "list"];
|
|
5206
|
-
var LAYOUT_LABEL = {
|
|
5207
|
-
grid: "Grid",
|
|
5208
|
-
kanban: "Kanban",
|
|
5209
|
-
calendar: "Calendar",
|
|
5210
|
-
gallery: "Gallery",
|
|
5211
|
-
timeline: "Timeline",
|
|
5212
|
-
list: "List"
|
|
5213
|
-
};
|
|
5214
|
-
function wordsList(words2) {
|
|
5215
|
-
const clean = words2.map((w) => w.trim()).filter((w) => w !== "");
|
|
5216
|
-
if (clean.length <= 1) return clean.join("");
|
|
5217
|
-
return `${clean.slice(0, -1).join(", ")} and ${clean[clean.length - 1]}`;
|
|
5218
|
-
}
|
|
5219
|
-
var VIEW_NEEDS = {
|
|
5220
|
-
grid: null,
|
|
5221
|
-
// A list reads nothing a table can lack: rows, titled, grouped only when the person chooses.
|
|
5222
|
-
list: null,
|
|
5223
|
-
kanban: {
|
|
5224
|
-
kind: "choice",
|
|
5225
|
-
viewKey: "groupField",
|
|
5226
|
-
blocking: true,
|
|
5227
|
-
starter: { label: "Status", type: "select", options: ["To do", "In progress", "Done"] },
|
|
5228
|
-
pick: "Pick the choice column the board's columns come from.",
|
|
5229
|
-
missing: "This table has no choice column to make the board's columns from.",
|
|
5230
|
-
does: (label) => `Make it work adds a ${label} column with the choices below and groups the board by it.`,
|
|
5231
|
-
ask: (label, options) => `Add a choice column called ${label} to this table${options.length > 0 ? ` with the choices ${wordsList(options)}` : ""}, then group the Kanban board by it.`
|
|
5232
|
-
},
|
|
5233
|
-
calendar: {
|
|
5234
|
-
kind: "date",
|
|
5235
|
-
viewKey: "dateField",
|
|
5236
|
-
blocking: true,
|
|
5237
|
-
starter: { label: "Date", type: "datetime" },
|
|
5238
|
-
pick: "Pick the date column the calendar places records by.",
|
|
5239
|
-
missing: "This table has no date column to place records on.",
|
|
5240
|
-
does: (label) => `Make it work adds a ${label} column and lays the calendar out by it.`,
|
|
5241
|
-
ask: (label) => `Add a date column called ${label} to this table, then lay the Calendar out by it.`
|
|
5242
|
-
},
|
|
5243
|
-
gallery: {
|
|
5244
|
-
kind: "file",
|
|
5245
|
-
viewKey: "imageField",
|
|
5246
|
-
blocking: false,
|
|
5247
|
-
starter: { label: "Photo", type: "attachment" },
|
|
5248
|
-
pick: "Pick the file column each card shows as its picture.",
|
|
5249
|
-
missing: "The cards have no picture because this table has no file column.",
|
|
5250
|
-
does: (label) => `Make it work adds a ${label} column and shows it on each card.`,
|
|
5251
|
-
ask: (label) => `Add a file column called ${label} to this table, then show it as the picture on each Gallery card.`
|
|
5252
|
-
},
|
|
5253
|
-
timeline: {
|
|
5254
|
-
kind: "date",
|
|
5255
|
-
viewKey: "dateField",
|
|
5256
|
-
blocking: true,
|
|
5257
|
-
starter: { label: "Start", type: "datetime" },
|
|
5258
|
-
pick: "Pick the date column each bar starts on.",
|
|
5259
|
-
missing: "This table has no date column to place records on.",
|
|
5260
|
-
does: (label) => `Make it work adds a ${label} column and lays the timeline out by it.`,
|
|
5261
|
-
ask: (label) => `Add a date column called ${label} to this table, then lay the Timeline out by it.`
|
|
5262
|
-
}
|
|
5263
|
-
};
|
|
5264
|
-
function freeColumnName(wanted, taken) {
|
|
5265
|
-
const held = new Set(taken.map((t) => t.trim().toLowerCase()));
|
|
5266
|
-
const base = wanted.trim() === "" ? "Column" : wanted.trim();
|
|
5267
|
-
if (!held.has(base.toLowerCase())) return base;
|
|
5268
|
-
for (let n = 2; n < 100; n += 1) {
|
|
5269
|
-
const next = `${base} ${n}`;
|
|
5270
|
-
if (!held.has(next.toLowerCase())) return next;
|
|
5271
|
-
}
|
|
5272
|
-
return base;
|
|
5273
|
-
}
|
|
5274
|
-
function viewOrderOf(definition) {
|
|
5275
|
-
const raw = definition?.["order"];
|
|
5276
|
-
return raw === "manual" ? "manual" : raw === "sorted" ? "sorted" : null;
|
|
5277
|
-
}
|
|
5278
|
-
function defaultViewOf(views) {
|
|
5279
|
-
return views.find((v) => v.isDefault);
|
|
5280
|
-
}
|
|
5281
|
-
var LAYOUT_FIELD_KIND = {
|
|
5282
|
-
grid: null,
|
|
5283
|
-
kanban: "choice",
|
|
5284
|
-
calendar: "date",
|
|
5285
|
-
gallery: "file",
|
|
5286
|
-
timeline: "date",
|
|
5287
|
-
list: null
|
|
5288
|
-
};
|
|
5289
|
-
var PAGE_VIEWS = [...VIEW_LAYOUTS, "dashboards", "archived"];
|
|
5290
|
-
var PAGE_VIEW_LABEL = {
|
|
5291
|
-
...LAYOUT_LABEL,
|
|
5292
|
-
dashboards: "Dashboards",
|
|
5293
|
-
archived: "Archived"
|
|
5294
|
-
};
|
|
5295
|
-
var PAGE_VIEW_SPELLINGS = {
|
|
5296
|
-
grid: "grid",
|
|
5297
|
-
table: "grid",
|
|
5298
|
-
rows: "grid",
|
|
5299
|
-
list: "list",
|
|
5300
|
-
kanban: "kanban",
|
|
5301
|
-
board: "kanban",
|
|
5302
|
-
pipeline: "kanban",
|
|
5303
|
-
calendar: "calendar",
|
|
5304
|
-
month: "calendar",
|
|
5305
|
-
schedule: "calendar",
|
|
5306
|
-
gallery: "gallery",
|
|
5307
|
-
cards: "gallery",
|
|
5308
|
-
timeline: "timeline",
|
|
5309
|
-
gantt: "timeline",
|
|
5310
|
-
dashboards: "dashboards",
|
|
5311
|
-
dashboard: "dashboards",
|
|
5312
|
-
charts: "dashboards",
|
|
5313
|
-
archived: "archived",
|
|
5314
|
-
archive: "archived",
|
|
5315
|
-
// The grid's row action says "Delete" and the store soft-deletes, so the word
|
|
5316
|
-
// a person types is as likely to be the one the button used as the one this
|
|
5317
|
-
// view is called. Both land in the same place; neither dies.
|
|
5318
|
-
deleted: "archived",
|
|
5319
|
-
trash: "archived",
|
|
5320
|
-
removed: "archived"
|
|
5321
|
-
};
|
|
5322
|
-
function pageViewFromParam(raw) {
|
|
5323
|
-
if (typeof raw !== "string") return null;
|
|
5324
|
-
const token2 = raw.trim().toLowerCase();
|
|
5325
|
-
if (token2 === "") return null;
|
|
5326
|
-
return PAGE_VIEW_SPELLINGS[token2] ?? null;
|
|
5327
|
-
}
|
|
5328
|
-
function unknownViewLine(raw) {
|
|
5329
|
-
return `The link asked for a view called \u201C${raw}\u201D, which this table has no view for, so you are looking at ${PAGE_VIEW_LABEL.grid}. The views this table has are ${PAGE_VIEWS.map((v) => PAGE_VIEW_LABEL[v]).join(", ")} \u2014 pick one above and the address follows it.`;
|
|
5330
|
-
}
|
|
5331
|
-
function viewDocument(spec) {
|
|
5332
|
-
const out = {
|
|
5333
|
-
// A layout the store does not keep yet is not sent: the view is saved as a grid (`STORE_KEPT_LAYOUTS`).
|
|
5334
|
-
layout: storeKeepsLayout(spec.layout) ? spec.layout : "grid",
|
|
5335
|
-
sorts: spec.sorts ?? [],
|
|
5336
|
-
is_default: spec.isDefault === true
|
|
5337
|
-
};
|
|
5338
|
-
if (spec.groupField) out["group_field"] = spec.groupField;
|
|
5339
|
-
if (spec.swimlaneField) out["swimlane_field"] = spec.swimlaneField;
|
|
5340
|
-
if (spec.collapsedColumns && spec.collapsedColumns.length > 0) out["collapsed_columns"] = spec.collapsedColumns;
|
|
5341
|
-
if (spec.measure) out["measure"] = spec.measure;
|
|
5342
|
-
if (spec.dateField) out["date_field"] = spec.dateField;
|
|
5343
|
-
if (STORE_KEEPS_TIMELINE && spec.startField) out["start_field"] = spec.startField;
|
|
5344
|
-
if (STORE_KEEPS_TIMELINE && spec.endField) out["end_field"] = spec.endField;
|
|
5345
|
-
if (spec.imageField) out["image_field"] = spec.imageField;
|
|
5346
|
-
if (spec.ruleId) out["rule_id"] = spec.ruleId;
|
|
5347
|
-
if (spec.where) out["where"] = spec.where;
|
|
5348
|
-
if (spec.presentation && !presentationIsEmpty(spec.presentation)) {
|
|
5349
|
-
out["presentation"] = JSON.parse(presentationDocument(spec.presentation));
|
|
5350
|
-
}
|
|
5351
|
-
return out;
|
|
5352
|
-
}
|
|
5353
|
-
function viewFromRow(row) {
|
|
5354
|
-
const data = row.definition ?? {};
|
|
5355
|
-
const k = viewSettings(data, row.filters && Object.keys(row.filters).length > 0 ? row.filters : null);
|
|
5356
|
-
const tableFromDefinition = typeof data["table_id"] === "string" && data["table_id"] !== "" ? data["table_id"] : null;
|
|
5357
|
-
return {
|
|
5358
|
-
id: row.view_id,
|
|
5359
|
-
name: row.name || "Untitled view",
|
|
5360
|
-
subject: row.table_id ?? tableFromDefinition ?? "",
|
|
5361
|
-
layout: k.layout,
|
|
5362
|
-
groupField: k.groupField,
|
|
5363
|
-
swimlaneField: k.swimlaneField,
|
|
5364
|
-
collapsedColumns: k.collapsedColumns,
|
|
5365
|
-
measure: k.measure,
|
|
5366
|
-
dateField: k.dateField,
|
|
5367
|
-
startField: k.startField,
|
|
5368
|
-
endField: k.endField,
|
|
5369
|
-
imageField: k.imageField,
|
|
5370
|
-
sorts: k.sorts,
|
|
5371
|
-
order: viewOrderOf(data),
|
|
5372
|
-
ruleId: k.ruleId,
|
|
5373
|
-
...k.filters ? { filters: k.filters } : {},
|
|
5374
|
-
where: k.where,
|
|
5375
|
-
// The older table's own default view, carried in by the mover, IS this table's default —
|
|
5376
|
-
// the mover wrote the row's column, which `custom.views` does not return. Read as anything
|
|
5377
|
-
// else, the page would seed a second "All records" beside it and open on that.
|
|
5378
|
-
isDefault: k.isDefault || k.movedFrom?.["kind"] === "default_view",
|
|
5379
|
-
presentation: k.presentation,
|
|
5380
|
-
movedFrom: k.movedFrom
|
|
5381
|
-
};
|
|
5382
|
-
}
|
|
5383
|
-
async function declareView(client, spec) {
|
|
5384
|
-
return client.viewDeclare({
|
|
5385
|
-
table_id: spec.subject,
|
|
5386
|
-
spec: {
|
|
5387
|
-
name: spec.name,
|
|
5388
|
-
...spec.filters ? { filters: spec.filters } : {},
|
|
5389
|
-
definition: viewDocument(spec)
|
|
5390
|
-
}
|
|
5391
|
-
});
|
|
5392
|
-
}
|
|
5393
|
-
async function saveViewPatch(client, tableId, viewId, patch) {
|
|
5394
|
-
const definition = viewPatchDocument(patch);
|
|
5395
|
-
const renamed = patch.name !== void 0 && patch.name.trim() !== "";
|
|
5396
|
-
const refiltered = patch.filters !== void 0;
|
|
5397
|
-
return client.viewDeclare({
|
|
5398
|
-
table_id: tableId,
|
|
5399
|
-
spec: {
|
|
5400
|
-
view_id: viewId,
|
|
5401
|
-
...renamed ? { name: patch.name.trim() } : {},
|
|
5402
|
-
...refiltered ? { filters: patch.filters ?? null } : {},
|
|
5403
|
-
definition
|
|
5404
|
-
}
|
|
5405
|
-
});
|
|
5406
|
-
}
|
|
5407
|
-
function viewPatchDocument(patch) {
|
|
5408
|
-
const { name: _name, subject: _subject, filters: _filters, ...keys } = patch;
|
|
5409
|
-
return viewSettingsPatch(keys);
|
|
5410
|
-
}
|
|
5411
|
-
function viewPatchFor(view, patch) {
|
|
5412
|
-
if (!view.isDefault) return patch;
|
|
5413
|
-
const { layout: _layout, isDefault: _isDefault, ...kept } = patch;
|
|
5414
|
-
return kept;
|
|
5415
|
-
}
|
|
5416
|
-
async function designateView(client, tableId, viewId, layout) {
|
|
5417
|
-
return client.viewDesignate({ table_id: tableId, view_id: viewId, layout });
|
|
5418
|
-
}
|
|
5419
|
-
|
|
5420
|
-
// src/viewLook.ts
|
|
5421
|
-
var LOOK_KEYS = [
|
|
5422
|
-
"layout",
|
|
5423
|
-
"groupField",
|
|
5424
|
-
"swimlaneField",
|
|
5425
|
-
"collapsedColumns",
|
|
5426
|
-
"measure",
|
|
5427
|
-
"dateField",
|
|
5428
|
-
"startField",
|
|
5429
|
-
"endField",
|
|
5430
|
-
"imageField",
|
|
5431
|
-
"sorts",
|
|
5432
|
-
"where",
|
|
5433
|
-
"presentation"
|
|
5434
|
-
];
|
|
5435
|
-
function lookPart(patch) {
|
|
5436
|
-
const out = {};
|
|
5437
|
-
for (const key of LOOK_KEYS) {
|
|
5438
|
-
if (patch[key] !== void 0) out[key] = patch[key];
|
|
5439
|
-
}
|
|
5440
|
-
return out;
|
|
5441
|
-
}
|
|
5442
|
-
function lookDocument(look) {
|
|
5443
|
-
return viewSettingsPatch(look);
|
|
5444
|
-
}
|
|
5445
|
-
function lookFromDocument(doc) {
|
|
5446
|
-
const data = doc ?? {};
|
|
5447
|
-
const read = viewSettings(data);
|
|
5448
|
-
const out = {};
|
|
5449
|
-
const has = (key) => Object.prototype.hasOwnProperty.call(data, key);
|
|
5450
|
-
if (has("layout") && VIEW_LAYOUTS.includes(String(data["layout"]))) {
|
|
5451
|
-
out.layout = data["layout"];
|
|
5452
|
-
}
|
|
5453
|
-
if (has("group_field")) out.groupField = read.groupField;
|
|
5454
|
-
if (has("swimlane_field")) out.swimlaneField = read.swimlaneField;
|
|
5455
|
-
if (has("collapsed_columns")) out.collapsedColumns = read.collapsedColumns;
|
|
5456
|
-
if (has("measure")) out.measure = read.measure;
|
|
5457
|
-
if (has("date_field")) out.dateField = read.dateField;
|
|
5458
|
-
if (has("start_field")) out.startField = read.startField;
|
|
5459
|
-
if (has("end_field")) out.endField = read.endField;
|
|
5460
|
-
if (has("image_field")) out.imageField = read.imageField;
|
|
5461
|
-
if (has("sorts")) out.sorts = read.sorts;
|
|
5462
|
-
if (has("where")) out.where = read.where;
|
|
5463
|
-
if (has("presentation")) out.presentation = parseGridPresentation(data["presentation"]);
|
|
5464
|
-
return out;
|
|
5465
|
-
}
|
|
5466
|
-
function applyLook(view, look) {
|
|
5467
|
-
if (!look) return view;
|
|
5468
|
-
return { ...view, ...look };
|
|
5469
|
-
}
|
|
5470
|
-
function lookDiffers(view, look) {
|
|
5471
|
-
if (!look) return false;
|
|
5472
|
-
const shown4 = applyLook(view, look);
|
|
5473
|
-
return LOOK_KEYS.some(
|
|
5474
|
-
(key) => look[key] !== void 0 && JSON.stringify(shown4[key] ?? null) !== JSON.stringify(view[key] ?? null)
|
|
5475
|
-
);
|
|
5476
|
-
}
|
|
5477
|
-
function saveToViewPlan(view, look) {
|
|
5478
|
-
const patch = viewPatchFor(view, look);
|
|
5479
|
-
const left = {};
|
|
5480
|
-
if (look.layout !== void 0 && patch.layout === void 0 && look.layout !== view.layout) left.layout = look.layout;
|
|
5481
|
-
return { patch, left: Object.keys(left).length > 0 ? left : null };
|
|
5482
|
-
}
|
|
5483
|
-
async function readLooks(client, tableId) {
|
|
5484
|
-
const answered = await client.viewLookRead({ table_id: tableId });
|
|
5485
|
-
if (!answered.ok) return answered;
|
|
5486
|
-
const out = {};
|
|
5487
|
-
for (const [viewId, row] of Object.entries(answered.data ?? {})) {
|
|
5488
|
-
out[viewId] = lookFromDocument(row?.look ?? null);
|
|
5489
|
-
}
|
|
5490
|
-
return { ok: true, data: out };
|
|
5491
|
-
}
|
|
5492
|
-
async function keepLook(client, tableId, viewId, look) {
|
|
5493
|
-
const doc = look ? lookDocument(look) : null;
|
|
5494
|
-
return client.viewLookSet({ table_id: tableId, view_id: viewId, look: doc && Object.keys(doc).length > 0 ? doc : null });
|
|
5495
|
-
}
|
|
5496
|
-
var LOOK_WORDS = {
|
|
5497
|
-
/** The reason, for a tooltip or a screen reader — never a line on the page (interface-text). */
|
|
5498
|
-
yours: "You changed how this view looks. Only you see it.",
|
|
5499
|
-
/** The visible label for the same fact. */
|
|
5500
|
-
yoursLabel: "Only you see this",
|
|
5501
|
-
saveToView: "Save to view",
|
|
5502
|
-
saveAsNew: "Save as new view",
|
|
5503
|
-
reset: "Reset to view",
|
|
5504
|
-
/** The one button your look's doors fold into when the toolbar row has no room for three. */
|
|
5505
|
-
folded: "Your look",
|
|
5506
|
-
newName: "Name for the new view"
|
|
4993
|
+
import * as base from "@ai-matrx/records/views";
|
|
4994
|
+
import {
|
|
4995
|
+
STORE_KEEPS_TIMELINE,
|
|
4996
|
+
STORE_KEPT_LAYOUTS,
|
|
4997
|
+
VIEW_KEYS,
|
|
4998
|
+
storeKeepsLayout,
|
|
4999
|
+
viewKeysFor,
|
|
5000
|
+
viewSettingsFor
|
|
5001
|
+
} from "@ai-matrx/records/views";
|
|
5002
|
+
var gridPresentationCodec = {
|
|
5003
|
+
parse: parseGridPresentation,
|
|
5004
|
+
isEmpty: presentationIsEmpty,
|
|
5005
|
+
toDocument: (presentation) => JSON.parse(presentationDocument(presentation))
|
|
5507
5006
|
};
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
function entityTableQuery(options = {}) {
|
|
5511
|
-
const search = (options.search ?? "").trim();
|
|
5512
|
-
return { ...options.pageSize ? { pageSize: options.pageSize } : {}, ...search ? { search } : {} };
|
|
5513
|
-
}
|
|
5514
|
-
function entityChartQuestion(input) {
|
|
5515
|
-
const m = input.measure ?? { op: "count" };
|
|
5516
|
-
return {
|
|
5517
|
-
...input.by ? { by: [input.by] } : {},
|
|
5518
|
-
show: [m.op === "count" ? "count" : { op: m.op, of: m.of }],
|
|
5519
|
-
...input.where ? { where: input.where } : {},
|
|
5520
|
-
...input.organization ? { organization: input.organization } : {}
|
|
5521
|
-
};
|
|
5522
|
-
}
|
|
5007
|
+
var boundViews = base.bindViewCodec(gridPresentationCodec);
|
|
5008
|
+
var { viewSettings, viewSettingsPatch } = boundViews;
|
|
5523
5009
|
|
|
5524
5010
|
// src/firstPage.ts
|
|
5525
|
-
|
|
5011
|
+
import {
|
|
5012
|
+
EMBEDDED_PAGE_SIZE,
|
|
5013
|
+
TABLE_PAGE_SIZE,
|
|
5014
|
+
firstGridPageArgs,
|
|
5015
|
+
serverRowsOf,
|
|
5016
|
+
viewFilterOf
|
|
5017
|
+
} from "@ai-matrx/records/first-page";
|
|
5018
|
+
var { firstGridPageRequest, askTablePageSeed } = bindFirstPageCodec(gridPresentationCodec);
|
|
5526
5019
|
|
|
5527
5020
|
// src/embeddedLook.tsx
|
|
5528
5021
|
var EMBEDDED_LOOK = { blankEmpty: true, choiceDot: true, plainRelation: true };
|
|
@@ -6777,7 +6270,7 @@ function RetiredValues({
|
|
|
6777
6270
|
}) {
|
|
6778
6271
|
const client = useRecordsClient7();
|
|
6779
6272
|
const [busy, setBusy] = useState20(null);
|
|
6780
|
-
const [
|
|
6273
|
+
const [refusal3, setRefusal] = useState20(null);
|
|
6781
6274
|
const [said2, setSaid] = useState20(null);
|
|
6782
6275
|
const [missing, setMissing] = useState20(null);
|
|
6783
6276
|
const kept = retiredValuesOf(document2);
|
|
@@ -6826,7 +6319,7 @@ function RetiredValues({
|
|
|
6826
6319
|
mayWrite ? /* @__PURE__ */ jsx26(Button11, { size: "sm", variant: "outline", className: "h-6 px-2 text-xs", disabled: busy !== null, onClick: () => void restore(entry, index), "data-records-retired-restore": "", children: busy === id ? "Restoring\u2026" : "Restore" }) : null
|
|
6827
6320
|
] }),
|
|
6828
6321
|
entry.reason ? /* @__PURE__ */ jsx26("p", { className: "text-[11px] text-muted-foreground", children: entry.reason }) : null,
|
|
6829
|
-
|
|
6322
|
+
refusal3?.key === id ? /* @__PURE__ */ jsx26(RefusalNotice, { error: refusal3.error }) : null,
|
|
6830
6323
|
missing === id ? /* @__PURE__ */ jsxs23("p", { className: "text-[11px] text-muted-foreground", children: [
|
|
6831
6324
|
"No earlier version of ",
|
|
6832
6325
|
name,
|
|
@@ -7681,7 +7174,7 @@ function ruleWords(rules) {
|
|
|
7681
7174
|
function rulesChanged(was, now) {
|
|
7682
7175
|
return ruleWords(was) !== ruleWords(now);
|
|
7683
7176
|
}
|
|
7684
|
-
function
|
|
7177
|
+
function holdsNumbers3(field2) {
|
|
7685
7178
|
return field2.type === "range";
|
|
7686
7179
|
}
|
|
7687
7180
|
function groupValue(value, numbers) {
|
|
@@ -7692,7 +7185,7 @@ function groupValue(value, numbers) {
|
|
|
7692
7185
|
function FieldRulePreview({ field: field2, tableId, rules }) {
|
|
7693
7186
|
const client = useRecordsClient9();
|
|
7694
7187
|
const [preview, setPreview] = useState23(null);
|
|
7695
|
-
const [
|
|
7188
|
+
const [refusal3, setRefusal] = useState23(null);
|
|
7696
7189
|
const key = useMemo11(() => ruleWords(rules), [rules]);
|
|
7697
7190
|
const latest = useRef13(rules);
|
|
7698
7191
|
latest.current = rules;
|
|
@@ -7708,7 +7201,7 @@ function FieldRulePreview({ field: field2, tableId, rules }) {
|
|
|
7708
7201
|
setRefusal(answer.error);
|
|
7709
7202
|
return;
|
|
7710
7203
|
}
|
|
7711
|
-
const numbers =
|
|
7204
|
+
const numbers = holdsNumbers3(field2);
|
|
7712
7205
|
const groups = answer.data.map((row) => ({ value: groupValue(row.groups[field2.key] ?? null, numbers), count: row.row_count }));
|
|
7713
7206
|
setPreview(previewRuleChange(latest.current, groups, answer.data.length >= PREVIEW_GROUPS2));
|
|
7714
7207
|
});
|
|
@@ -7718,7 +7211,7 @@ function FieldRulePreview({ field: field2, tableId, rules }) {
|
|
|
7718
7211
|
clearTimeout(timer);
|
|
7719
7212
|
};
|
|
7720
7213
|
}, [client, tableId, field2.key, key]);
|
|
7721
|
-
if (
|
|
7214
|
+
if (refusal3) return /* @__PURE__ */ jsx31(RefusalNotice, { error: refusal3 });
|
|
7722
7215
|
if (!preview) {
|
|
7723
7216
|
return /* @__PURE__ */ jsxs27("p", { className: "text-[11px] text-muted-foreground", "data-records-rule-preview": "counting", children: [
|
|
7724
7217
|
"Counting ",
|
|
@@ -7779,9 +7272,9 @@ function choiceDisplayPatch(field2, rows) {
|
|
|
7779
7272
|
}
|
|
7780
7273
|
function lookFollowsRenames(field2, look, renames) {
|
|
7781
7274
|
if (renames.size === 0) return look;
|
|
7782
|
-
const
|
|
7783
|
-
const choices =
|
|
7784
|
-
if (!
|
|
7275
|
+
const base2 = look ?? displayFormatOf(field2);
|
|
7276
|
+
const choices = base2 && Array.isArray(base2.options["choices"]) ? base2.options["choices"] : null;
|
|
7277
|
+
if (!base2 || !choices) return look;
|
|
7785
7278
|
let moved = false;
|
|
7786
7279
|
const next = choices.map((c) => {
|
|
7787
7280
|
const was = typeof c["value"] === "string" ? c["value"] : null;
|
|
@@ -7791,11 +7284,11 @@ function lookFollowsRenames(field2, look, renames) {
|
|
|
7791
7284
|
return { ...c, value: now };
|
|
7792
7285
|
});
|
|
7793
7286
|
if (!moved) return look;
|
|
7794
|
-
return { id:
|
|
7287
|
+
return { id: base2.id, options: { ...base2.options, choices: next } };
|
|
7795
7288
|
}
|
|
7796
7289
|
function choiceLookFromList(field2, start, rows) {
|
|
7797
|
-
const
|
|
7798
|
-
const colorRows =
|
|
7290
|
+
const base2 = startingChoiceColors(field2, start.map((r) => r.words.trim()).filter((w) => w !== ""));
|
|
7291
|
+
const colorRows = base2.map((row) => {
|
|
7799
7292
|
const was = start.find((r) => choiceWord(r.words) === choiceWord(row.value));
|
|
7800
7293
|
const now = was?.id ? rows.find((r) => r.id === was.id) : void 0;
|
|
7801
7294
|
return now ? { value: row.value, color: now.color ?? null } : row;
|
|
@@ -8248,9 +7741,9 @@ function storageOf(field2) {
|
|
|
8248
7741
|
}
|
|
8249
7742
|
}
|
|
8250
7743
|
function formatMenu(field2) {
|
|
8251
|
-
const
|
|
8252
|
-
if (
|
|
8253
|
-
if (
|
|
7744
|
+
const base2 = storageOf(field2);
|
|
7745
|
+
if (base2 === null) return { groups: [], otherKinds: [] };
|
|
7746
|
+
if (base2 === "formula") {
|
|
8254
7747
|
const groups2 = [];
|
|
8255
7748
|
for (const def of FIELD_FORMAT_LIST) {
|
|
8256
7749
|
if (neverALook(def) || KIND_WORD[def.id] || def.id === "boolean") continue;
|
|
@@ -8260,7 +7753,7 @@ function formatMenu(field2) {
|
|
|
8260
7753
|
}
|
|
8261
7754
|
return { groups: groups2, otherKinds: [] };
|
|
8262
7755
|
}
|
|
8263
|
-
const groups = groupedFormatsForBase(
|
|
7756
|
+
const groups = groupedFormatsForBase(base2).map((g) => ({ group: g.group, formats: g.formats.filter((d) => !neverALook(d) && !KIND_WORD[d.id]) })).filter((g) => g.formats.length > 0);
|
|
8264
7757
|
const own3 = new Set(groups.flatMap((g) => g.formats.map((d) => d.id)));
|
|
8265
7758
|
const otherKinds = [];
|
|
8266
7759
|
for (const def of FIELD_FORMAT_LIST) {
|
|
@@ -10832,7 +10325,7 @@ function FieldControl({ field: field2, value, onChange, disabled, id, autoOpen,
|
|
|
10832
10325
|
}
|
|
10833
10326
|
function TypedWordsControl({ field: field2, value, onChange, disabled, id }) {
|
|
10834
10327
|
const [text, setText] = useState32(() => openingText(field2, value));
|
|
10835
|
-
const [
|
|
10328
|
+
const [refusal3, setRefusal] = useState32(null);
|
|
10836
10329
|
const [why, setWhy] = useState32(void 0);
|
|
10837
10330
|
const sent = useRef18(value);
|
|
10838
10331
|
useEffect22(() => {
|
|
@@ -10863,11 +10356,11 @@ function TypedWordsControl({ field: field2, value, onChange, disabled, id }) {
|
|
|
10863
10356
|
value: text,
|
|
10864
10357
|
disabled,
|
|
10865
10358
|
autoComplete: "off",
|
|
10866
|
-
"aria-invalid":
|
|
10359
|
+
"aria-invalid": refusal3 ? true : void 0,
|
|
10867
10360
|
placeholder: helper ? typedDatePlaceholder(helper) : void 0,
|
|
10868
10361
|
onChange: (e) => retype(e.target.value),
|
|
10869
10362
|
onBlur: () => {
|
|
10870
|
-
if (!
|
|
10363
|
+
if (!refusal3) return;
|
|
10871
10364
|
setText(openingText(field2, sent.current));
|
|
10872
10365
|
setRefusal(null);
|
|
10873
10366
|
}
|
|
@@ -10875,7 +10368,7 @@ function TypedWordsControl({ field: field2, value, onChange, disabled, id }) {
|
|
|
10875
10368
|
),
|
|
10876
10369
|
helper && !disabled ? /* @__PURE__ */ jsx42(TypedDateHelper, { kind: helper, text, onText: retype, label: fieldName(field2) }) : null
|
|
10877
10370
|
] }),
|
|
10878
|
-
|
|
10371
|
+
refusal3 ? /* @__PURE__ */ jsx42(FloatingRefusal, { text: refusal3, why }) : null
|
|
10879
10372
|
] });
|
|
10880
10373
|
}
|
|
10881
10374
|
function typedDatePlaceholder(helper) {
|
|
@@ -10979,7 +10472,7 @@ function inTheStoresOrder(options) {
|
|
|
10979
10472
|
function OptionControl({ field: field2, value, onChange, disabled, id, autoOpen, onClose, onCancel, addsChoices, initialSearch, asForm, onChosen }) {
|
|
10980
10473
|
const client = useOptionalRecordsClient10();
|
|
10981
10474
|
const [options, setOptions] = useState32(null);
|
|
10982
|
-
const [
|
|
10475
|
+
const [refusal3, setRefusal] = useState32(null);
|
|
10983
10476
|
const [reread, setReread] = useState32(0);
|
|
10984
10477
|
useEffect22(() => {
|
|
10985
10478
|
if (!client) return;
|
|
@@ -11011,8 +10504,8 @@ function OptionControl({ field: field2, value, onChange, disabled, id, autoOpen,
|
|
|
11011
10504
|
/* @__PURE__ */ jsx42("p", { className: "text-xs text-muted-foreground", children: "This is normally picked from a list. A page answered without an account cannot read that list, so type your answer and whoever receives it will match it up." })
|
|
11012
10505
|
] });
|
|
11013
10506
|
}
|
|
11014
|
-
if (
|
|
11015
|
-
return /* @__PURE__ */ jsx42("div", { id, children: /* @__PURE__ */ jsx42(RefusalLine, { error:
|
|
10507
|
+
if (refusal3)
|
|
10508
|
+
return /* @__PURE__ */ jsx42("div", { id, children: /* @__PURE__ */ jsx42(RefusalLine, { error: refusal3 }) });
|
|
11016
10509
|
if (!options) return /* @__PURE__ */ jsx42("p", { id, className: "text-xs text-muted-foreground", children: "Reading this field's choices\u2026" });
|
|
11017
10510
|
if (asForm && options.length > 0) {
|
|
11018
10511
|
const titled = (option) => recordName(option.data, null, "Unnamed choice");
|
|
@@ -11751,7 +11244,7 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
11751
11244
|
startedFrom.current = null;
|
|
11752
11245
|
}, []);
|
|
11753
11246
|
const writeCellNow = useCallback10(
|
|
11754
|
-
async (rowId, key, value,
|
|
11247
|
+
async (rowId, key, value, base2, resent = false) => {
|
|
11755
11248
|
const id = cellKey(rowId, key);
|
|
11756
11249
|
const adding = isChoiceAddition(value) ? value : null;
|
|
11757
11250
|
const shown4 = adding ? adding.value : value;
|
|
@@ -11768,7 +11261,7 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
11768
11261
|
let version = await versionOf(source, versions.current, versionReads.current, rowId);
|
|
11769
11262
|
const drawnNow = await source.seen(rowId);
|
|
11770
11263
|
const storedNow = rowsNow.current.find((r) => r.id === rowId)?.document?.[key];
|
|
11771
|
-
if (drawnNow !== null && (version === null || drawnNow > version) && sameValue(storedNow,
|
|
11264
|
+
if (drawnNow !== null && (version === null || drawnNow > version) && sameValue(storedNow, base2)) {
|
|
11772
11265
|
version = drawnNow;
|
|
11773
11266
|
rememberVersion(versions.current, rowId, drawnNow);
|
|
11774
11267
|
}
|
|
@@ -11797,13 +11290,13 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
11797
11290
|
if (written.ok) {
|
|
11798
11291
|
rememberVersion(versions.current, rowId, written.data);
|
|
11799
11292
|
source.wrote(rowId, written.data);
|
|
11800
|
-
settling.current.set(id,
|
|
11801
|
-
writtenRef.current?.({ rowId, key, before:
|
|
11293
|
+
settling.current.set(id, base2);
|
|
11294
|
+
writtenRef.current?.({ rowId, key, before: base2, after: shown4, version: written.data });
|
|
11802
11295
|
afterWrite();
|
|
11803
11296
|
return;
|
|
11804
11297
|
}
|
|
11805
11298
|
if (isUnsentWrite(written.error)) {
|
|
11806
|
-
setRefusals((held) => ({ ...held, [id]: { error: written.error, conflict: null, attempted: value, unsent: true, base } }));
|
|
11299
|
+
setRefusals((held) => ({ ...held, [id]: { error: written.error, conflict: null, attempted: value, unsent: true, base: base2 } }));
|
|
11807
11300
|
return;
|
|
11808
11301
|
}
|
|
11809
11302
|
setOptimistic((held) => {
|
|
@@ -11815,8 +11308,8 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
11815
11308
|
if (written.error.code === "stale_write") {
|
|
11816
11309
|
if (conflict) rememberVersion(versions.current, rowId, conflict.current_version);
|
|
11817
11310
|
else versions.current.delete(rowId);
|
|
11818
|
-
if (conflict && !resent && sameValue(conflict.contested_fields[key],
|
|
11819
|
-
await writeCellNow(rowId, key, value,
|
|
11311
|
+
if (conflict && !resent && sameValue(conflict.contested_fields[key], base2)) {
|
|
11312
|
+
await writeCellNow(rowId, key, value, base2, true);
|
|
11820
11313
|
return;
|
|
11821
11314
|
}
|
|
11822
11315
|
}
|
|
@@ -11833,9 +11326,9 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
11833
11326
|
[client, reload, afterWrite, source]
|
|
11834
11327
|
);
|
|
11835
11328
|
const writeCell = useCallback10(
|
|
11836
|
-
(rowId, key, value,
|
|
11329
|
+
(rowId, key, value, base2) => {
|
|
11837
11330
|
const behind = queues.current.get(rowId) ?? Promise.resolve();
|
|
11838
|
-
const next = behind.then(() => writeCellNow(rowId, key, value,
|
|
11331
|
+
const next = behind.then(() => writeCellNow(rowId, key, value, base2));
|
|
11839
11332
|
queues.current.set(
|
|
11840
11333
|
rowId,
|
|
11841
11334
|
next.then(
|
|
@@ -12188,7 +11681,7 @@ function GridCell({
|
|
|
12188
11681
|
};
|
|
12189
11682
|
const value = editing ? editing.valueFor(row, field2) : row.document?.[field2.key];
|
|
12190
11683
|
const state = editing ? editing.stateOf(row.id, field2.key) : null;
|
|
12191
|
-
const
|
|
11684
|
+
const refusal3 = editing ? editing.refusalOf(row.id, field2.key) : null;
|
|
12192
11685
|
const editable = Boolean(editing) && canWrite && fieldIsEditable(field2);
|
|
12193
11686
|
if (open && editing) {
|
|
12194
11687
|
return /* @__PURE__ */ jsxs39("span", { "data-records-open-cell": "", className: "relative block w-full min-w-0", children: [
|
|
@@ -12225,10 +11718,10 @@ function GridCell({
|
|
|
12225
11718
|
// state they are in, so only Discard is offered. It is INSIDE the open
|
|
12226
11719
|
// cell, so pressing Discard is not "focus left the cell" — which would
|
|
12227
11720
|
// commit the refused value one more time on its way out.
|
|
12228
|
-
|
|
11721
|
+
refusal3 && !refusal3.conflict ? /* @__PURE__ */ jsx44(
|
|
12229
11722
|
RefusalNotice,
|
|
12230
11723
|
{
|
|
12231
|
-
error:
|
|
11724
|
+
error: refusal3.error,
|
|
12232
11725
|
className: "py-1.5 text-left",
|
|
12233
11726
|
onDiscard: () => editing.discard(row.id, field2.key)
|
|
12234
11727
|
}
|
|
@@ -12253,14 +11746,14 @@ function GridCell({
|
|
|
12253
11746
|
}
|
|
12254
11747
|
),
|
|
12255
11748
|
answered ? null : /* @__PURE__ */ jsx44("span", { className: "text-xs text-muted-foreground", title: "nobody has answered this yet", children: "\u2014" }),
|
|
12256
|
-
|
|
11749
|
+
refusal3 ? /* @__PURE__ */ jsx44(CellRefusalNotice, { refusal: refusal3, field: field2, row, editing, typed: false }) : null
|
|
12257
11750
|
] });
|
|
12258
11751
|
}
|
|
12259
11752
|
if (editable && format?.id === "rating") {
|
|
12260
11753
|
return /* @__PURE__ */ jsxs39("span", { "data-matrx-cell-control": "", className: "relative flex h-full w-full flex-wrap items-center gap-1.5", children: [
|
|
12261
11754
|
/* @__PURE__ */ jsx44(FormattedValue, { value, format, onRate: (next) => editing?.setCell(row.id, field2.key, next), selectFirst: true }),
|
|
12262
11755
|
state === "saving" ? /* @__PURE__ */ jsx44("span", { "data-records-cell-saving": "", className: "pointer-events-none absolute right-1 top-1/2 z-10 -translate-y-1/2 rounded bg-card/90 px-1 text-[10px] text-muted-foreground", children: "Saving\u2026" }) : null,
|
|
12263
|
-
|
|
11756
|
+
refusal3 ? /* @__PURE__ */ jsx44(CellRefusalNotice, { refusal: refusal3, field: field2, row, editing, typed: false }) : null
|
|
12264
11757
|
] });
|
|
12265
11758
|
}
|
|
12266
11759
|
const openThisCell = (event) => {
|
|
@@ -12382,40 +11875,40 @@ function GridCell({
|
|
|
12382
11875
|
) : null
|
|
12383
11876
|
] }),
|
|
12384
11877
|
state === "saving" ? /* @__PURE__ */ jsx44("span", { "data-records-cell-saving": "", className: "pointer-events-none absolute right-1 top-1/2 z-10 -translate-y-1/2 rounded bg-card/90 px-1 text-[10px] text-muted-foreground", children: "Saving\u2026" }) : null,
|
|
12385
|
-
|
|
11878
|
+
refusal3 ? /* @__PURE__ */ jsx44(CellRefusalNotice, { refusal: refusal3, field: field2, row, editing, typed: true }) : null
|
|
12386
11879
|
]
|
|
12387
11880
|
}
|
|
12388
11881
|
)
|
|
12389
11882
|
);
|
|
12390
11883
|
}
|
|
12391
11884
|
function CellRefusalNotice({
|
|
12392
|
-
refusal:
|
|
11885
|
+
refusal: refusal3,
|
|
12393
11886
|
field: field2,
|
|
12394
11887
|
row,
|
|
12395
11888
|
editing,
|
|
12396
11889
|
typed: typed2
|
|
12397
11890
|
}) {
|
|
12398
11891
|
const [open, setOpen] = useState34(true);
|
|
12399
|
-
const line =
|
|
12400
|
-
const notice =
|
|
11892
|
+
const line = refusal3.unsent ? UNSENT_LINE : refusalLineForAPerson(refusal3.error);
|
|
11893
|
+
const notice = refusal3.unsent ? (
|
|
12401
11894
|
// NOT SENT, NOT REFUSED: what was typed is still in the cell; it goes again once online.
|
|
12402
11895
|
/* @__PURE__ */ jsxs39("div", { className: "flex flex-col gap-1.5 px-3 py-2 text-xs", "data-records-cell-unsent": "", children: [
|
|
12403
11896
|
/* @__PURE__ */ jsx44("span", { className: "font-medium", children: UNSENT_LINE }),
|
|
12404
|
-
/* @__PURE__ */ jsx44("span", { className: "max-w-[16rem] truncate text-muted-foreground", title: valueInALine(
|
|
11897
|
+
/* @__PURE__ */ jsx44("span", { className: "max-w-[16rem] truncate text-muted-foreground", title: valueInALine(refusal3.attempted), children: valueInALine(refusal3.attempted) }),
|
|
12405
11898
|
/* @__PURE__ */ jsxs39("span", { className: "flex flex-wrap gap-1", children: [
|
|
12406
11899
|
/* @__PURE__ */ jsx44(Button19, { size: "sm", variant: "outline", className: "h-6", "data-records-cell-try-now": "", onClick: () => editing?.tryNow(row.id, field2.key), children: "Try now" }),
|
|
12407
11900
|
/* @__PURE__ */ jsx44(Button19, { size: "sm", variant: "ghost", className: "h-6", "data-records-cell-discard": "", onClick: () => editing?.discard(row.id, field2.key), children: "Discard" })
|
|
12408
11901
|
] })
|
|
12409
11902
|
] })
|
|
12410
|
-
) :
|
|
11903
|
+
) : refusal3.conflict ? /* @__PURE__ */ jsx44(
|
|
12411
11904
|
RefusalNotice,
|
|
12412
11905
|
{
|
|
12413
|
-
error:
|
|
11906
|
+
error: refusal3.error,
|
|
12414
11907
|
className: "py-1.5 text-left",
|
|
12415
11908
|
actions: /* @__PURE__ */ jsxs39("span", { className: "flex flex-col gap-1", "data-refusal-conflict": "", children: [
|
|
12416
11909
|
/* @__PURE__ */ jsxs39("span", { className: "text-[11px]", children: [
|
|
12417
11910
|
"Theirs: ",
|
|
12418
|
-
/* @__PURE__ */ jsx44("strong", { children: formatTheirs(
|
|
11911
|
+
/* @__PURE__ */ jsx44("strong", { children: formatTheirs(refusal3.conflict, field2.key) })
|
|
12419
11912
|
] }),
|
|
12420
11913
|
/* @__PURE__ */ jsxs39("span", { className: "flex flex-wrap gap-1", children: [
|
|
12421
11914
|
/* @__PURE__ */ jsx44(Button19, { size: "sm", variant: "outline", onClick: () => editing?.retry(row.id, field2.key), children: "Try again" }),
|
|
@@ -12426,7 +11919,7 @@ function CellRefusalNotice({
|
|
|
12426
11919
|
) : /* @__PURE__ */ jsx44(
|
|
12427
11920
|
RefusalNotice,
|
|
12428
11921
|
{
|
|
12429
|
-
error:
|
|
11922
|
+
error: refusal3.error,
|
|
12430
11923
|
className: "py-1.5 text-left",
|
|
12431
11924
|
...typed2 ? { onKeepEditing: () => editing?.keepEditing(row.id, field2.key) } : {},
|
|
12432
11925
|
onDiscard: () => editing?.discard(row.id, field2.key)
|
|
@@ -12440,8 +11933,8 @@ function CellRefusalNotice({
|
|
|
12440
11933
|
"data-records-cell-refusal-line": "",
|
|
12441
11934
|
title: line,
|
|
12442
11935
|
"aria-label": line,
|
|
12443
|
-
"data-records-cell-unsent-mark":
|
|
12444
|
-
className: `absolute right-1 top-1/2 z-10 flex h-4 w-4 -translate-y-1/2 items-center justify-center rounded-full text-[10px] font-bold leading-none ${
|
|
11936
|
+
"data-records-cell-unsent-mark": refusal3.unsent ? "" : void 0,
|
|
11937
|
+
className: `absolute right-1 top-1/2 z-10 flex h-4 w-4 -translate-y-1/2 items-center justify-center rounded-full text-[10px] font-bold leading-none ${refusal3.unsent ? "bg-amber-500 text-white" : "bg-destructive text-destructive-foreground"}`,
|
|
12445
11938
|
children: "!"
|
|
12446
11939
|
}
|
|
12447
11940
|
) }),
|
|
@@ -13090,7 +12583,7 @@ function MergeRecordDialog({ tableId, record, open, onOpenChange, onMerged }) {
|
|
|
13090
12583
|
const records = useRecords3(tableId, { pageSize: 200 });
|
|
13091
12584
|
const [other, setOther] = useState37(null);
|
|
13092
12585
|
const [busy, setBusy] = useState37(false);
|
|
13093
|
-
const [
|
|
12586
|
+
const [refusal3, setRefusal] = useState37(null);
|
|
13094
12587
|
const options = useMemo15(
|
|
13095
12588
|
() => (records.data?.rows ?? []).filter((row) => row.id !== record.id).map((row) => ({ value: row.id, label: rowNameIn(table.data ?? null, row) })),
|
|
13096
12589
|
[records.data, record.id, table.data]
|
|
@@ -13160,7 +12653,7 @@ function MergeRecordDialog({ tableId, record, open, onOpenChange, onMerged }) {
|
|
|
13160
12653
|
ariaLabel: "Record to merge"
|
|
13161
12654
|
}
|
|
13162
12655
|
),
|
|
13163
|
-
|
|
12656
|
+
refusal3 ? /* @__PURE__ */ jsx47(RefusalNotice, { error: refusal3 }) : null,
|
|
13164
12657
|
/* @__PURE__ */ jsxs42(DialogFooter, { children: [
|
|
13165
12658
|
/* @__PURE__ */ jsx47(Button21, { variant: "ghost", size: "sm", onClick: () => close(false), disabled: busy, children: "Cancel" }),
|
|
13166
12659
|
/* @__PURE__ */ jsx47(Button21, { size: "sm", onClick: () => void merge(), disabled: !other || busy, "data-records-merge-go": "", children: busy ? "Merging\u2026" : "Merge" })
|
|
@@ -13344,7 +12837,7 @@ function useGridColours(args) {
|
|
|
13344
12837
|
[client, tableId, decorations, notify]
|
|
13345
12838
|
);
|
|
13346
12839
|
const idOf = useCallback12((key) => fields.find((f) => f.key === key), [fields]);
|
|
13347
|
-
const
|
|
12840
|
+
const refusal3 = mayColour ? void 0 : whyNot;
|
|
13348
12841
|
const headerItem = useCallback12(
|
|
13349
12842
|
(columnKey) => {
|
|
13350
12843
|
if (!enabled) return null;
|
|
@@ -13359,7 +12852,7 @@ function useGridColours(args) {
|
|
|
13359
12852
|
id: "col-colour",
|
|
13360
12853
|
label: "Colour by\u2026",
|
|
13361
12854
|
icon: "palette",
|
|
13362
|
-
disabledReason:
|
|
12855
|
+
disabledReason: refusal3,
|
|
13363
12856
|
submenu: [
|
|
13364
12857
|
byThis ? {
|
|
13365
12858
|
id: "col-colour-off",
|
|
@@ -13395,7 +12888,7 @@ function useGridColours(args) {
|
|
|
13395
12888
|
]
|
|
13396
12889
|
};
|
|
13397
12890
|
},
|
|
13398
|
-
[enabled, idOf, decorations.data,
|
|
12891
|
+
[enabled, idOf, decorations.data, refusal3, write]
|
|
13399
12892
|
);
|
|
13400
12893
|
const cellItem = useCallback12(
|
|
13401
12894
|
(rowId, columnKey) => {
|
|
@@ -13407,7 +12900,7 @@ function useGridColours(args) {
|
|
|
13407
12900
|
id: "cell-highlight",
|
|
13408
12901
|
label: "Highlight cell",
|
|
13409
12902
|
icon: "palette",
|
|
13410
|
-
disabledReason:
|
|
12903
|
+
disabledReason: refusal3,
|
|
13411
12904
|
submenu: swatches(
|
|
13412
12905
|
"cell-highlight",
|
|
13413
12906
|
current,
|
|
@@ -13415,7 +12908,7 @@ function useGridColours(args) {
|
|
|
13415
12908
|
)
|
|
13416
12909
|
};
|
|
13417
12910
|
},
|
|
13418
|
-
[enabled, idOf, decorations.data,
|
|
12911
|
+
[enabled, idOf, decorations.data, refusal3, write]
|
|
13419
12912
|
);
|
|
13420
12913
|
const cellsItem = useCallback12(
|
|
13421
12914
|
(cells) => {
|
|
@@ -13425,7 +12918,7 @@ function useGridColours(args) {
|
|
|
13425
12918
|
id: "sel-highlight",
|
|
13426
12919
|
label: `Highlight ${n} cells`,
|
|
13427
12920
|
icon: "palette",
|
|
13428
|
-
disabledReason:
|
|
12921
|
+
disabledReason: refusal3,
|
|
13429
12922
|
submenu: swatches("sel-highlight", void 0, (color) => {
|
|
13430
12923
|
void (async () => {
|
|
13431
12924
|
let kept = 0;
|
|
@@ -13445,7 +12938,7 @@ function useGridColours(args) {
|
|
|
13445
12938
|
})
|
|
13446
12939
|
};
|
|
13447
12940
|
},
|
|
13448
|
-
[enabled, idOf,
|
|
12941
|
+
[enabled, idOf, refusal3, client, tableId, decorations, notify]
|
|
13449
12942
|
);
|
|
13450
12943
|
const rowItem = useCallback12(
|
|
13451
12944
|
(rowId) => {
|
|
@@ -13455,7 +12948,7 @@ function useGridColours(args) {
|
|
|
13455
12948
|
id: "row-highlight",
|
|
13456
12949
|
label: "Highlight row",
|
|
13457
12950
|
icon: "palette",
|
|
13458
|
-
disabledReason:
|
|
12951
|
+
disabledReason: refusal3,
|
|
13459
12952
|
submenu: swatches(
|
|
13460
12953
|
"row-highlight",
|
|
13461
12954
|
current,
|
|
@@ -13463,7 +12956,7 @@ function useGridColours(args) {
|
|
|
13463
12956
|
)
|
|
13464
12957
|
};
|
|
13465
12958
|
},
|
|
13466
|
-
[enabled, decorations.data,
|
|
12959
|
+
[enabled, decorations.data, refusal3, write]
|
|
13467
12960
|
);
|
|
13468
12961
|
const dialogs = enabled ? /* @__PURE__ */ jsx48(
|
|
13469
12962
|
ColourRulesDialog,
|
|
@@ -14235,7 +13728,7 @@ function stepOf(step2, original) {
|
|
|
14235
13728
|
return { field: field2, set: "value", value: step2.value };
|
|
14236
13729
|
}
|
|
14237
13730
|
function actionOf(draft, original) {
|
|
14238
|
-
const
|
|
13731
|
+
const base2 = {
|
|
14239
13732
|
...draft.id ? { id: draft.id } : {},
|
|
14240
13733
|
name: draft.name.trim(),
|
|
14241
13734
|
kind: draft.kind,
|
|
@@ -14243,9 +13736,9 @@ function actionOf(draft, original) {
|
|
|
14243
13736
|
...draft.color ? { color: draft.color } : {},
|
|
14244
13737
|
...draft.icon ? { icon: draft.icon } : {}
|
|
14245
13738
|
};
|
|
14246
|
-
if (draft.kind === "agent") return { ...
|
|
13739
|
+
if (draft.kind === "agent") return { ...base2, prompt: draft.prompt };
|
|
14247
13740
|
return {
|
|
14248
|
-
...
|
|
13741
|
+
...base2,
|
|
14249
13742
|
steps: draft.steps.map((s, i) => stepOf(s, original?.steps?.[i]))
|
|
14250
13743
|
};
|
|
14251
13744
|
}
|
|
@@ -15511,19 +15004,19 @@ function planPastedBlock(args) {
|
|
|
15511
15004
|
accepted[key] = judged.value;
|
|
15512
15005
|
}
|
|
15513
15006
|
const predicted = predictValueRefusals(args.fields, accepted);
|
|
15514
|
-
for (const
|
|
15515
|
-
const key =
|
|
15007
|
+
for (const refusal3 of predicted) {
|
|
15008
|
+
const key = refusal3.field_key;
|
|
15516
15009
|
if (key === void 0) continue;
|
|
15517
15010
|
const cell2 = built.find((b) => b.key === key && b.refusal === null);
|
|
15518
15011
|
if (!cell2) continue;
|
|
15519
|
-
cell2.refusal =
|
|
15012
|
+
cell2.refusal = refusal3.message;
|
|
15520
15013
|
cell2.value = null;
|
|
15521
15014
|
delete accepted[key];
|
|
15522
15015
|
refusals.push({
|
|
15523
15016
|
fromLine,
|
|
15524
15017
|
column: fieldName(byKey.get(key) ?? { key }),
|
|
15525
15018
|
raw: cell2.raw,
|
|
15526
|
-
why:
|
|
15019
|
+
why: refusal3.message
|
|
15527
15020
|
});
|
|
15528
15021
|
}
|
|
15529
15022
|
cells += Object.keys(accepted).length;
|
|
@@ -15727,8 +15220,8 @@ function useMergedGridControls(args) {
|
|
|
15727
15220
|
setHeld(null);
|
|
15728
15221
|
}, [keptKey]);
|
|
15729
15222
|
const order = useMemo21(() => {
|
|
15730
|
-
const
|
|
15731
|
-
const known = columnsInKeptOrder(fieldKeys,
|
|
15223
|
+
const base2 = held?.order ?? columnsInKeptOrder(fieldKeys, keptOrder);
|
|
15224
|
+
const known = columnsInKeptOrder(fieldKeys, base2);
|
|
15732
15225
|
if (frozenKeys.size === 0) return known;
|
|
15733
15226
|
return [...known.filter((k) => frozenKeys.has(k)), ...known.filter((k) => !frozenKeys.has(k))];
|
|
15734
15227
|
}, [held, fieldKeys, keptOrder, frozenKeys]);
|
|
@@ -15784,10 +15277,10 @@ function useMergedGridControls(args) {
|
|
|
15784
15277
|
return;
|
|
15785
15278
|
}
|
|
15786
15279
|
let cancelled = false;
|
|
15787
|
-
const [keys, filters,
|
|
15280
|
+
const [keys, filters, base2, searched] = JSON.parse(countQuestionKey);
|
|
15788
15281
|
for (const key of keys) {
|
|
15789
15282
|
const { [key]: _own, ...others } = filters;
|
|
15790
|
-
const asked2 = storeQuestion(fieldsRef.current,
|
|
15283
|
+
const asked2 = storeQuestion(fieldsRef.current, base2 ?? void 0, others);
|
|
15791
15284
|
void (0, askOnce_exports.askOnce)(
|
|
15792
15285
|
client,
|
|
15793
15286
|
`value_counts:${tableId}:${key}:${searched}:${JSON.stringify(asked2.filter ?? null)}`,
|
|
@@ -16403,9 +15896,9 @@ function readersThrough(fields, key) {
|
|
|
16403
15896
|
});
|
|
16404
15897
|
}
|
|
16405
15898
|
function backLinkSentence(column, readers = [], tableName2 = null) {
|
|
16406
|
-
const
|
|
16407
|
-
if (readers.length === 0) return
|
|
16408
|
-
return `${readersSentence(readers.length, tableName2)} ${
|
|
15899
|
+
const base2 = `It goes when ${column.source_field_label} is archived on ${column.source_table_name}. Archiving it removes the links it holds there too; it can be brought back from Archived.`;
|
|
15900
|
+
if (readers.length === 0) return base2;
|
|
15901
|
+
return `${readersSentence(readers.length, tableName2)} ${base2}`;
|
|
16409
15902
|
}
|
|
16410
15903
|
function afterMenuLayerCloses(next) {
|
|
16411
15904
|
if (typeof window === "undefined") return next();
|
|
@@ -17744,8 +17237,8 @@ function useDrillDefinition(source) {
|
|
|
17744
17237
|
}, [client, key]);
|
|
17745
17238
|
return state.key === key ? { def: state.def, error: state.error } : { def: null, error: null };
|
|
17746
17239
|
}
|
|
17747
|
-
function drillWhere(
|
|
17748
|
-
const where = { ...
|
|
17240
|
+
function drillWhere(base2, trail, booleans) {
|
|
17241
|
+
const where = { ...base2 ?? {} };
|
|
17749
17242
|
for (const w of trail) {
|
|
17750
17243
|
const { key, grain } = parseDimensionRef2(w.dim);
|
|
17751
17244
|
if (grain) where[w.dim] = w.value;
|
|
@@ -17924,10 +17417,10 @@ function useDrill(args) {
|
|
|
17924
17417
|
const booleans = useMemo25(() => new Set((def?.dimensions ?? []).filter((d) => d.kind === "boolean").map((d) => d.key)), [def]);
|
|
17925
17418
|
const baseKey = JSON.stringify(args.base ?? []);
|
|
17926
17419
|
const filter = useMemo25(() => {
|
|
17927
|
-
const
|
|
17928
|
-
if (
|
|
17420
|
+
const base2 = JSON.parse(baseKey);
|
|
17421
|
+
if (base2.length === 0) return args.filter;
|
|
17929
17422
|
const out = { ...args.filter ?? {} };
|
|
17930
|
-
for (const b of
|
|
17423
|
+
for (const b of base2) out[b.key] = b.value;
|
|
17931
17424
|
return out;
|
|
17932
17425
|
}, [args.filter, baseKey]);
|
|
17933
17426
|
const where = useMemo25(() => drillWhere(filter, question.where, booleans), [filter, question.where, booleans]);
|
|
@@ -18056,17 +17549,17 @@ function trailClause(fields, w) {
|
|
|
18056
17549
|
}
|
|
18057
17550
|
return { key, value: w.value, field: field2 };
|
|
18058
17551
|
}
|
|
18059
|
-
function filterWithTrail(fields,
|
|
18060
|
-
if (trail.length === 0) return
|
|
18061
|
-
if (!
|
|
18062
|
-
const flat = { ...
|
|
17552
|
+
function filterWithTrail(fields, base2, trail) {
|
|
17553
|
+
if (trail.length === 0) return base2;
|
|
17554
|
+
if (!base2 || !isRuleFilter2(base2)) {
|
|
17555
|
+
const flat = { ...base2 ?? {} };
|
|
18063
17556
|
for (const w of trail) {
|
|
18064
17557
|
const clause = trailClause(fields, w);
|
|
18065
17558
|
flat[clause.key] = clause.value;
|
|
18066
17559
|
}
|
|
18067
17560
|
return flat;
|
|
18068
17561
|
}
|
|
18069
|
-
const args = [
|
|
17562
|
+
const args = [base2];
|
|
18070
17563
|
for (const w of trail) {
|
|
18071
17564
|
const clause = trailClause(fields, w);
|
|
18072
17565
|
if (!clause.field) continue;
|
|
@@ -18080,14 +17573,14 @@ function filterWithTrail(fields, base, trail) {
|
|
|
18080
17573
|
}
|
|
18081
17574
|
return { op: "and", args };
|
|
18082
17575
|
}
|
|
18083
|
-
function filterWithWindow(fields,
|
|
18084
|
-
if (!
|
|
17576
|
+
function filterWithWindow(fields, base2, key, range) {
|
|
17577
|
+
if (!base2 || !isRuleFilter2(base2)) return { ...base2 ?? {}, [key]: { from: range.from, to: range.to } };
|
|
18085
17578
|
const field2 = fields.find((f) => f.key === key);
|
|
18086
|
-
if (!field2) return
|
|
17579
|
+
if (!field2) return base2;
|
|
18087
17580
|
const ref = { field: field2.id };
|
|
18088
17581
|
return {
|
|
18089
17582
|
op: "and",
|
|
18090
|
-
args: [
|
|
17583
|
+
args: [base2, { op: "gte", args: [ref, { const: range.from }] }, { op: "lt", args: [ref, { const: range.to }] }]
|
|
18091
17584
|
};
|
|
18092
17585
|
}
|
|
18093
17586
|
function useGridDrillQuestion(args) {
|
|
@@ -18769,7 +18262,7 @@ function columnForField(field2, editing, mayWriteRow, whyNotRow, look, onAskWhoC
|
|
|
18769
18262
|
...look?.frozen ? { frozen: true, width: Math.max(FROZEN_COLUMN_WIDTH, defaultColumnWidth(field2)) } : { width: defaultColumnWidth(field2) },
|
|
18770
18263
|
// A column that holds numbers filters as numbers (=, <, >, between) — the record number too,
|
|
18771
18264
|
// which is worked out but kept (review 2: the autonumber header offered "Contains").
|
|
18772
|
-
filter: filterRefusal(field2) !== null ? false : editorKindFor(field2) === "select" || editorKindFor(field2) === "multi_select" ? "select" :
|
|
18265
|
+
filter: filterRefusal(field2) !== null ? false : editorKindFor(field2) === "select" || editorKindFor(field2) === "multi_select" ? "select" : holdsNumbers2(field2) ? "number" : "auto",
|
|
18773
18266
|
// THE MENU'S VALUE LIST WEARS THE CHOICES' COLOURS (lane CELL-EDITORS, night walk 2026-10-06): the
|
|
18774
18267
|
// same chip the cell draws, never bare words beside a coloured column.
|
|
18775
18268
|
...editorKindFor(field2) === "select" || editorKindFor(field2) === "multi_select" ? { filterValueClass: (value, label) => choiceChipLookOf(field2, value, label).className } : {},
|
|
@@ -18896,6 +18389,18 @@ function withTypeMark(field2, header) {
|
|
|
18896
18389
|
// src/ReverseColumns.tsx
|
|
18897
18390
|
import { useCallback as useCallback20, useEffect as useEffect44, useMemo as useMemo27, useRef as useRef29, useState as useState55, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
18898
18391
|
import { isReverseField } from "@ai-matrx/records";
|
|
18392
|
+
|
|
18393
|
+
// src/groupReads.ts
|
|
18394
|
+
import {
|
|
18395
|
+
REVERSE_CELL_CHIPS,
|
|
18396
|
+
choiceFieldKeys,
|
|
18397
|
+
groupFactMeasures,
|
|
18398
|
+
groupedPageSort,
|
|
18399
|
+
isPlainGrouping,
|
|
18400
|
+
summaryBarMeasures
|
|
18401
|
+
} from "@ai-matrx/records/first-page";
|
|
18402
|
+
|
|
18403
|
+
// src/ReverseColumns.tsx
|
|
18899
18404
|
import { useFields as useFields6, useOptionalRecordsClient as useOptionalRecordsClient11, useReverseColumns as useReverseColumns3, useReverseLinks, useTable as useTable4 } from "@ai-matrx/records/react";
|
|
18900
18405
|
import { Button as Button37, Dialog as Dialog11, DialogContent as DialogContent11, DialogHeader as DialogHeader11, DialogTitle as DialogTitle11, Popover as Popover8, PopoverContent as PopoverContent8, PopoverTrigger as PopoverTrigger8, Separator as Separator4, Skeleton as Skeleton5, cn as cn36 } from "@ai-matrx/design-system";
|
|
18901
18406
|
import { Fragment as Fragment19, jsx as jsx65, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
@@ -19356,10 +18861,10 @@ function PastePreview({
|
|
|
19356
18861
|
/* @__PURE__ */ jsx67(PlanTable, { plan }),
|
|
19357
18862
|
plan.refusals.length > 0 ? /* @__PURE__ */ jsxs62("div", { "data-matrx-paste-refusals": true, className: "flex flex-col gap-1", children: [
|
|
19358
18863
|
/* @__PURE__ */ jsx67("p", { className: "text-xs font-medium", children: plan.refusals.length === 1 ? "One cell will be left alone:" : `${plan.refusals.length} cells will be left alone:` }),
|
|
19359
|
-
/* @__PURE__ */ jsx67("ul", { className: "flex flex-col gap-1", children: plan.refusals.slice(0, 12).map((
|
|
19360
|
-
/* @__PURE__ */ jsx67("span", { className: "font-medium", children:
|
|
18864
|
+
/* @__PURE__ */ jsx67("ul", { className: "flex flex-col gap-1", children: plan.refusals.slice(0, 12).map((refusal3, index) => /* @__PURE__ */ jsxs62("li", { className: "text-xs text-muted-foreground", children: [
|
|
18865
|
+
/* @__PURE__ */ jsx67("span", { className: "font-medium", children: refusal3.fromLine > 0 ? `Row ${refusal3.fromLine}, ${refusal3.column}` : refusal3.column }),
|
|
19361
18866
|
" \u2014 ",
|
|
19362
|
-
|
|
18867
|
+
refusal3.why
|
|
19363
18868
|
] }, index)) }),
|
|
19364
18869
|
plan.refusals.length > 12 ? /* @__PURE__ */ jsxs62("p", { className: "text-xs text-muted-foreground", children: [
|
|
19365
18870
|
plan.refusals.length - 12,
|
|
@@ -19836,8 +19341,8 @@ function offerDownload(name, text, type = "text/csv") {
|
|
|
19836
19341
|
return true;
|
|
19837
19342
|
}
|
|
19838
19343
|
function refusedFileName(sourceName) {
|
|
19839
|
-
const
|
|
19840
|
-
return `${
|
|
19344
|
+
const base2 = (sourceName ?? "import").replace(/\.(csv|xlsx)$/i, "");
|
|
19345
|
+
return `${base2} \u2014 rows not added.csv`;
|
|
19841
19346
|
}
|
|
19842
19347
|
|
|
19843
19348
|
// src/ImportWizard.tsx
|
|
@@ -21291,11 +20796,11 @@ function cellWords(raw) {
|
|
|
21291
20796
|
function uniqueLabels(raw) {
|
|
21292
20797
|
const seen = /* @__PURE__ */ new Map();
|
|
21293
20798
|
return raw.map((label, index) => {
|
|
21294
|
-
const
|
|
21295
|
-
const key =
|
|
20799
|
+
const base2 = label.trim() || `Column ${index + 1}`;
|
|
20800
|
+
const key = base2.toLowerCase();
|
|
21296
20801
|
const count = (seen.get(key) ?? 0) + 1;
|
|
21297
20802
|
seen.set(key, count);
|
|
21298
|
-
return count === 1 ?
|
|
20803
|
+
return count === 1 ? base2 : `${base2} ${count}`;
|
|
21299
20804
|
});
|
|
21300
20805
|
}
|
|
21301
20806
|
function rowsOf(headers, matrix) {
|
|
@@ -21356,7 +20861,7 @@ function recordsFromPairs(pairs) {
|
|
|
21356
20861
|
if (current.size > 0) records.push(current);
|
|
21357
20862
|
return records;
|
|
21358
20863
|
}
|
|
21359
|
-
function shapeFromRecords(records,
|
|
20864
|
+
function shapeFromRecords(records, base2, from) {
|
|
21360
20865
|
const order = [];
|
|
21361
20866
|
for (const r of records) for (const k of r.keys()) if (!order.some((o) => o.toLowerCase() === k.toLowerCase())) order.push(k);
|
|
21362
20867
|
const headers = uniqueLabels(order);
|
|
@@ -21369,7 +20874,7 @@ function shapeFromRecords(records, base, from) {
|
|
|
21369
20874
|
return row;
|
|
21370
20875
|
});
|
|
21371
20876
|
return {
|
|
21372
|
-
...
|
|
20877
|
+
...base2,
|
|
21373
20878
|
kind: "key_value",
|
|
21374
20879
|
headers,
|
|
21375
20880
|
rows,
|
|
@@ -21948,7 +21453,7 @@ function valueListKind(field2) {
|
|
|
21948
21453
|
if (kind === "text" || kind === "long_text" || kind === "email" || kind === "phone" || kind === "url") return "words";
|
|
21949
21454
|
if (kind === "datetime" || kind === "date") return "days";
|
|
21950
21455
|
if (kind === "checkbox") return "yesno";
|
|
21951
|
-
if (
|
|
21456
|
+
if (holdsNumbers2(field2) || kind === "rating") return "numbers";
|
|
21952
21457
|
return "loaded";
|
|
21953
21458
|
}
|
|
21954
21459
|
function noValueList(columnId2) {
|
|
@@ -22214,35 +21719,35 @@ function useGridUndo(args) {
|
|
|
22214
21719
|
if (!step2) return;
|
|
22215
21720
|
setBusy(true);
|
|
22216
21721
|
const changes = changesFor(step2, direction, known.current);
|
|
22217
|
-
let
|
|
21722
|
+
let refusal3 = null;
|
|
22218
21723
|
if (direction === "redo" && (step2.created?.length ?? 0) > 0) {
|
|
22219
21724
|
const answers = await Promise.all((step2.created ?? []).map((id) => client.recordRestore({ record_id: id })));
|
|
22220
21725
|
const failed = answers.find((a) => !a.ok);
|
|
22221
|
-
if (failed && !failed.ok)
|
|
21726
|
+
if (failed && !failed.ok) refusal3 = failed.error;
|
|
22222
21727
|
}
|
|
22223
|
-
if (!
|
|
21728
|
+
if (!refusal3 && step2.retiredField) {
|
|
22224
21729
|
const fieldId = step2.retiredField.fieldId;
|
|
22225
21730
|
const done = direction === "undo" ? await client.fieldRestore({ field_id: fieldId }) : await client.fieldRetire({ field_id: fieldId });
|
|
22226
|
-
if (!done.ok)
|
|
21731
|
+
if (!done.ok) refusal3 = done.error;
|
|
22227
21732
|
else tableShapeChanged6(tableId);
|
|
22228
21733
|
}
|
|
22229
|
-
if (!
|
|
21734
|
+
if (!refusal3 && changes.length > 0) {
|
|
22230
21735
|
const done = await (0, recordVersions_exports.changeRecordsAt)(client, { table_id: tableId, changes });
|
|
22231
|
-
if (!done.ok)
|
|
21736
|
+
if (!done.ok) refusal3 = done.error;
|
|
22232
21737
|
else {
|
|
22233
21738
|
for (const result of done.data ?? []) if (result.op === "update") known.current.set(result.id, result.version);
|
|
22234
21739
|
onVersions?.((done.data ?? []).flatMap((r) => r.op === "update" ? [{ id: r.id, version: r.version }] : []));
|
|
22235
21740
|
}
|
|
22236
21741
|
}
|
|
22237
|
-
if (!
|
|
21742
|
+
if (!refusal3 && direction === "undo" && (step2.archived?.length ?? 0) > 0) {
|
|
22238
21743
|
const answers = await Promise.all((step2.archived ?? []).map((id) => client.recordRestore({ record_id: id })));
|
|
22239
21744
|
const failed = answers.find((a) => !a.ok);
|
|
22240
|
-
if (failed && !failed.ok)
|
|
21745
|
+
if (failed && !failed.ok) refusal3 = failed.error;
|
|
22241
21746
|
}
|
|
22242
21747
|
setBusy(false);
|
|
22243
|
-
if (
|
|
22244
|
-
setNotice({ says: `${direction === "undo" ? "Undo" : "Redo"} changed nothing: ${refusalSentence(
|
|
22245
|
-
if ((0, recordVersions_exports.isChangedElsewhere)(
|
|
21748
|
+
if (refusal3) {
|
|
21749
|
+
setNotice({ says: `${direction === "undo" ? "Undo" : "Redo"} changed nothing: ${refusalSentence(refusal3)}`, refusal: refusal3, canUndo: false });
|
|
21750
|
+
if ((0, recordVersions_exports.isChangedElsewhere)(refusal3)) reload();
|
|
22246
21751
|
return;
|
|
22247
21752
|
}
|
|
22248
21753
|
forget(step2.cells.map((c) => ({ rowId: c.rowId, key: c.key })));
|
|
@@ -22973,7 +22478,7 @@ function useGridBulk(args) {
|
|
|
22973
22478
|
const client = useRecordsClient37();
|
|
22974
22479
|
const { tableId, rows, fields, noun, nounPlural, reload, forget, pushUndo: pushUndo2, versions } = args;
|
|
22975
22480
|
const [busy, setBusy] = useState62(false);
|
|
22976
|
-
const [
|
|
22481
|
+
const [refusal3, setRefusal] = useState62(null);
|
|
22977
22482
|
const send = useCallback26(
|
|
22978
22483
|
async (changes) => {
|
|
22979
22484
|
setBusy(true);
|
|
@@ -23037,7 +22542,7 @@ function useGridBulk(args) {
|
|
|
23037
22542
|
},
|
|
23038
22543
|
[send, rows, pushUndo2, reload, noun, nounPlural]
|
|
23039
22544
|
);
|
|
23040
|
-
return { busy, refusal:
|
|
22545
|
+
return { busy, refusal: refusal3, clearRefusal: () => setRefusal(null), apply, duplicate, archive };
|
|
23041
22546
|
}
|
|
23042
22547
|
function BulkActions({
|
|
23043
22548
|
ids,
|
|
@@ -23158,6 +22663,31 @@ import { useEffect as useEffect52, useMemo as useMemo34, useRef as useRef35, use
|
|
|
23158
22663
|
import { useRecordsClient as useRecordsClient38 } from "@ai-matrx/records/react";
|
|
23159
22664
|
import { stableFilterKey as stableFilterKey2 } from "@ai-matrx/records";
|
|
23160
22665
|
import { Button as Button43, ConfirmDialog as ConfirmDialog4, Popover as Popover9, PopoverContent as PopoverContent9, PopoverTrigger as PopoverTrigger9, cn as cn38 } from "@ai-matrx/design-system";
|
|
22666
|
+
|
|
22667
|
+
// src/views.ts
|
|
22668
|
+
import {
|
|
22669
|
+
STORE_KEEPS_TIMELINE as STORE_KEEPS_TIMELINE2,
|
|
22670
|
+
STORE_KEPT_LAYOUTS as STORE_KEPT_LAYOUTS2,
|
|
22671
|
+
storeKeepsLayout as storeKeepsLayout2,
|
|
22672
|
+
VIEW_LAYOUTS,
|
|
22673
|
+
LAYOUT_LABEL,
|
|
22674
|
+
wordsList,
|
|
22675
|
+
VIEW_NEEDS,
|
|
22676
|
+
freeColumnName,
|
|
22677
|
+
viewOrderOf,
|
|
22678
|
+
defaultViewOf,
|
|
22679
|
+
LAYOUT_FIELD_KIND,
|
|
22680
|
+
PAGE_VIEWS,
|
|
22681
|
+
PAGE_VIEW_LABEL,
|
|
22682
|
+
pageViewFromParam,
|
|
22683
|
+
unknownViewLine,
|
|
22684
|
+
makeDefaultLabel,
|
|
22685
|
+
designateView,
|
|
22686
|
+
viewPatchFor
|
|
22687
|
+
} from "@ai-matrx/records/views";
|
|
22688
|
+
var { viewDocument, viewFromRow, declareView, saveViewPatch, viewPatchDocument } = boundViews;
|
|
22689
|
+
|
|
22690
|
+
// src/handOrder.tsx
|
|
23161
22691
|
import { jsx as jsx76, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
23162
22692
|
function sortArrow(direction) {
|
|
23163
22693
|
return direction === "asc" ? "\u2191" : "\u2193";
|
|
@@ -25716,6 +25246,11 @@ import {
|
|
|
25716
25246
|
useEntityWrite,
|
|
25717
25247
|
useOptionalEntityScope
|
|
25718
25248
|
} from "@ai-matrx/records/entity/react";
|
|
25249
|
+
|
|
25250
|
+
// src/entityQuery.ts
|
|
25251
|
+
import { entityChartQuestion, entityTableQuery } from "@ai-matrx/records/first-page";
|
|
25252
|
+
|
|
25253
|
+
// src/entityTable.tsx
|
|
25719
25254
|
import { Fragment as Fragment27, jsx as jsx78 } from "react/jsx-runtime";
|
|
25720
25255
|
function EntityDataScope({ children }) {
|
|
25721
25256
|
const above = useOptionalEntityScope();
|
|
@@ -26446,19 +25981,19 @@ function fieldsForNewColumns(columns) {
|
|
|
26446
25981
|
let key = tokenFor(column.label) || `column_${i + 1}`;
|
|
26447
25982
|
while (keys.has(key)) key = `${key}_${i + 1}`;
|
|
26448
25983
|
keys.add(key);
|
|
26449
|
-
const
|
|
25984
|
+
const base2 = { key, label: column.label, sort: (i + 1) * 10, required: false };
|
|
26450
25985
|
switch (column.type) {
|
|
26451
25986
|
case "date":
|
|
26452
|
-
return { ...
|
|
25987
|
+
return { ...base2, type: "datetime", kind: "date" };
|
|
26453
25988
|
case "datetime":
|
|
26454
|
-
return { ...
|
|
25989
|
+
return { ...base2, type: "datetime", kind: "datetime" };
|
|
26455
25990
|
case "currency":
|
|
26456
|
-
return { ...
|
|
25991
|
+
return { ...base2, type: "currency", unit: "$" };
|
|
26457
25992
|
case "select":
|
|
26458
25993
|
case "multi_select":
|
|
26459
|
-
return { ...
|
|
25994
|
+
return { ...base2, type: column.type, multi: column.type === "multi_select", options: column.options ?? [] };
|
|
26460
25995
|
default:
|
|
26461
|
-
return { ...
|
|
25996
|
+
return { ...base2, type: column.type };
|
|
26462
25997
|
}
|
|
26463
25998
|
});
|
|
26464
25999
|
}
|
|
@@ -27124,15 +26659,15 @@ function objectActionForKey(actions, event) {
|
|
|
27124
26659
|
const id = Object.keys(TABLE_ACTION_KEYS).find((k) => TABLE_ACTION_KEYS[k].code === event.code);
|
|
27125
26660
|
return id ? actions.find((a) => a.id === id) ?? null : null;
|
|
27126
26661
|
}
|
|
27127
|
-
function action(
|
|
27128
|
-
const chord = TABLE_ACTION_KEYS[
|
|
27129
|
-
if (chord &&
|
|
26662
|
+
function action(base2, needs, input, perform) {
|
|
26663
|
+
const chord = TABLE_ACTION_KEYS[base2.id];
|
|
26664
|
+
if (chord && base2.shortcut === void 0) base2 = { ...base2, shortcut: chord.label };
|
|
27130
26665
|
const refused = rightsReason(input.rights, needs, input.table);
|
|
27131
|
-
if (refused !== null) return { ...
|
|
26666
|
+
if (refused !== null) return { ...base2, disabledReason: refused, run: NOOP };
|
|
27132
26667
|
if (perform === void 0) {
|
|
27133
|
-
return { ...
|
|
26668
|
+
return { ...base2, disabledReason: input.host.unavailableReasons?.[base2.id] ?? ACTION_NOT_HERE_REASON, run: NOOP };
|
|
27134
26669
|
}
|
|
27135
|
-
return { ...
|
|
26670
|
+
return { ...base2, run: perform };
|
|
27136
26671
|
}
|
|
27137
26672
|
function bind(handler, table) {
|
|
27138
26673
|
return handler ? () => handler(table) : void 0;
|
|
@@ -27203,9 +26738,9 @@ function tableActions(input) {
|
|
|
27203
26738
|
];
|
|
27204
26739
|
return withExtensions(built, host.extend ? host.extend(table, input.rights) : []);
|
|
27205
26740
|
}
|
|
27206
|
-
function withExtensions(
|
|
27207
|
-
if (extra.length === 0) return [...
|
|
27208
|
-
const seen = new Set(
|
|
26741
|
+
function withExtensions(base2, extra) {
|
|
26742
|
+
if (extra.length === 0) return [...base2];
|
|
26743
|
+
const seen = new Set(base2.map((a) => a.id));
|
|
27209
26744
|
for (const entry of extra) {
|
|
27210
26745
|
if (entry.group === "danger") {
|
|
27211
26746
|
throw new Error(`Object action "${entry.id}": the danger group is closed to extensions.`);
|
|
@@ -27220,7 +26755,7 @@ function withExtensions(base, extra) {
|
|
|
27220
26755
|
}
|
|
27221
26756
|
const out = [];
|
|
27222
26757
|
for (const group of OBJECT_ACTION_GROUPS) {
|
|
27223
|
-
out.push(...
|
|
26758
|
+
out.push(...base2.filter((a) => a.group === group.id), ...extra.filter((a) => a.group === group.id));
|
|
27224
26759
|
}
|
|
27225
26760
|
return out;
|
|
27226
26761
|
}
|
|
@@ -27426,7 +26961,7 @@ function ArchivedBuiltOn({ tableId, onRestored }) {
|
|
|
27426
26961
|
const [things, setThings] = useState68(null);
|
|
27427
26962
|
const [error, setError] = useState68(null);
|
|
27428
26963
|
const [restoring, setRestoring] = useState68(null);
|
|
27429
|
-
const [
|
|
26964
|
+
const [refusal3, setRefusal] = useState68(null);
|
|
27430
26965
|
const [said2, setSaid] = useState68(null);
|
|
27431
26966
|
const read = useCallback30(async () => {
|
|
27432
26967
|
const [forms, checklists] = await Promise.all([
|
|
@@ -27479,7 +27014,7 @@ function ArchivedBuiltOn({ tableId, onRestored }) {
|
|
|
27479
27014
|
" \xB7 archived ",
|
|
27480
27015
|
archivedWhen(thing.archivedAt)
|
|
27481
27016
|
] }),
|
|
27482
|
-
|
|
27017
|
+
refusal3 && refusal3.id === thing.id ? /* @__PURE__ */ jsx87(RefusalNotice, { error: refusal3.error, className: "mt-2" }) : null
|
|
27483
27018
|
] }),
|
|
27484
27019
|
thing.whyNot ? /* @__PURE__ */ jsx87("span", { className: "text-xs text-muted-foreground", children: thing.whyNot }) : /* @__PURE__ */ jsx87(
|
|
27485
27020
|
Button50,
|
|
@@ -28323,20 +27858,20 @@ function draftsFor(headers, rows) {
|
|
|
28323
27858
|
function keysFor(labels) {
|
|
28324
27859
|
const used = /* @__PURE__ */ new Set();
|
|
28325
27860
|
return labels.map((label, i) => {
|
|
28326
|
-
const
|
|
28327
|
-
let key =
|
|
27861
|
+
const base2 = tokenFor(label) === "table" && !/table/i.test(label) ? `column_${i + 1}` : tokenFor(label);
|
|
27862
|
+
let key = base2;
|
|
28328
27863
|
let n = 2;
|
|
28329
|
-
while (used.has(key)) key = `${
|
|
27864
|
+
while (used.has(key)) key = `${base2}_${n++}`;
|
|
28330
27865
|
used.add(key);
|
|
28331
27866
|
return key;
|
|
28332
27867
|
});
|
|
28333
27868
|
}
|
|
28334
27869
|
function freeName(name, taken) {
|
|
28335
27870
|
const lower = new Set(taken.map((t) => t.trim().toLowerCase()));
|
|
28336
|
-
const
|
|
28337
|
-
if (!lower.has(
|
|
28338
|
-
for (let n = 2; n < 100; n += 1) if (!lower.has(`${
|
|
28339
|
-
return `${
|
|
27871
|
+
const base2 = name.trim() || "Saved table";
|
|
27872
|
+
if (!lower.has(base2.toLowerCase())) return base2;
|
|
27873
|
+
for (let n = 2; n < 100; n += 1) if (!lower.has(`${base2} ${n}`.toLowerCase())) return `${base2} ${n}`;
|
|
27874
|
+
return `${base2} ${Date.now()}`;
|
|
28340
27875
|
}
|
|
28341
27876
|
async function sha256Text(text) {
|
|
28342
27877
|
const subtle = globalThis.crypto?.subtle;
|
|
@@ -29256,11 +28791,11 @@ import { Badge as Badge14, Button as Button61, Separator as Separator8, cn as cn
|
|
|
29256
28791
|
var TableRestoreRefused = class extends Error {
|
|
29257
28792
|
refusal;
|
|
29258
28793
|
sentence;
|
|
29259
|
-
constructor(
|
|
29260
|
-
const sentence2 = refusalSentence(
|
|
28794
|
+
constructor(refusal3) {
|
|
28795
|
+
const sentence2 = refusalSentence(refusal3);
|
|
29261
28796
|
super(sentence2);
|
|
29262
28797
|
this.name = "TableRestoreRefused";
|
|
29263
|
-
this.refusal =
|
|
28798
|
+
this.refusal = refusal3;
|
|
29264
28799
|
this.sentence = sentence2;
|
|
29265
28800
|
}
|
|
29266
28801
|
};
|
|
@@ -30778,6 +30313,22 @@ function usePlatformTable(spec) {
|
|
|
30778
30313
|
return state;
|
|
30779
30314
|
}
|
|
30780
30315
|
|
|
30316
|
+
// src/viewLook.ts
|
|
30317
|
+
import { applyLook, lookDiffers, lookPart, saveToViewPlan } from "@ai-matrx/records/views";
|
|
30318
|
+
var { lookDocument, lookFromDocument, readLooks, keepLook } = boundViews;
|
|
30319
|
+
var LOOK_WORDS = {
|
|
30320
|
+
/** The reason, for a tooltip or a screen reader — never a line on the page (interface-text). */
|
|
30321
|
+
yours: "You changed how this view looks. Only you see it.",
|
|
30322
|
+
/** The visible label for the same fact. */
|
|
30323
|
+
yoursLabel: "Only you see this",
|
|
30324
|
+
saveToView: "Save to view",
|
|
30325
|
+
saveAsNew: "Save as new view",
|
|
30326
|
+
reset: "Reset to view",
|
|
30327
|
+
/** The one button your look's doors fold into when the toolbar row has no room for three. */
|
|
30328
|
+
folded: "Your look",
|
|
30329
|
+
newName: "Name for the new view"
|
|
30330
|
+
};
|
|
30331
|
+
|
|
30781
30332
|
// src/ViewSwitcher.tsx
|
|
30782
30333
|
import { useEffect as useEffect79, useMemo as useMemo55, useState as useState93 } from "react";
|
|
30783
30334
|
import { mayDrag as mayDrag4, useFields as useFields18, useRecordPage as useRecordPage2, useRecordsClient as useRecordsClient65, useTable as useTable18 } from "@ai-matrx/records/react";
|
|
@@ -31072,13 +30623,13 @@ function recordLink(tableId, recordId, origin = DEFAULT_ACTION_ORIGIN) {
|
|
|
31072
30623
|
}
|
|
31073
30624
|
var NOOP2 = () => {
|
|
31074
30625
|
};
|
|
31075
|
-
function action2(
|
|
30626
|
+
function action2(base2, needs, input, perform) {
|
|
31076
30627
|
const refused = rightsReason(input.rights, needs);
|
|
31077
|
-
if (refused !== null) return { ...
|
|
30628
|
+
if (refused !== null) return { ...base2, disabledReason: refused, run: NOOP2 };
|
|
31078
30629
|
if (perform === void 0) {
|
|
31079
|
-
return { ...
|
|
30630
|
+
return { ...base2, disabledReason: input.host.unavailableReasons?.[base2.id] ?? ACTION_NOT_HERE_REASON, run: NOOP2 };
|
|
31080
30631
|
}
|
|
31081
|
-
return { ...
|
|
30632
|
+
return { ...base2, run: perform };
|
|
31082
30633
|
}
|
|
31083
30634
|
function bind2(handler, record) {
|
|
31084
30635
|
return handler ? () => handler(record) : void 0;
|
|
@@ -33845,12 +33396,12 @@ function viewNeedFor(layout) {
|
|
|
33845
33396
|
return VIEW_NEEDS[layout];
|
|
33846
33397
|
}
|
|
33847
33398
|
function columnDeclarationFor(need, label, options, fields) {
|
|
33848
|
-
const
|
|
33399
|
+
const base2 = { label: label.trim(), sort: nextFieldSort(fields) };
|
|
33849
33400
|
if (need.starter.type === "select") {
|
|
33850
|
-
return { ...
|
|
33401
|
+
return { ...base2, parity_type: "select", options: options.map((o) => o.trim()).filter((o) => o !== "") };
|
|
33851
33402
|
}
|
|
33852
|
-
if (need.starter.type === "datetime") return { ...
|
|
33853
|
-
return { ...
|
|
33403
|
+
if (need.starter.type === "datetime") return { ...base2, parity_type: "datetime", kind: "date" };
|
|
33404
|
+
return { ...base2, parity_type: "attachment" };
|
|
33854
33405
|
}
|
|
33855
33406
|
var askedFor = /* @__PURE__ */ new Map();
|
|
33856
33407
|
var askKey = (tableId, layout) => `${tableId}:${layout}`;
|
|
@@ -34730,10 +34281,10 @@ function Board({
|
|
|
34730
34281
|
...view.endField ? { endKey: view.endField } : {},
|
|
34731
34282
|
groupKey: view.groupField ?? null,
|
|
34732
34283
|
...view.presentation?.style?.colorBy !== void 0 ? { colorKey: view.presentation.style.colorBy?.field ?? null } : {},
|
|
34733
|
-
layoutKept: remembered &&
|
|
34284
|
+
layoutKept: remembered && STORE_KEEPS_TIMELINE2,
|
|
34734
34285
|
onSettingsChange: (patch) => {
|
|
34735
34286
|
if (patch.startKey !== void 0) {
|
|
34736
|
-
onChange({ startField: patch.startKey, ...
|
|
34287
|
+
onChange({ startField: patch.startKey, ...STORE_KEEPS_TIMELINE2 ? {} : { dateField: patch.startKey } });
|
|
34737
34288
|
}
|
|
34738
34289
|
if (patch.endKey !== void 0) onChange({ endField: patch.endKey });
|
|
34739
34290
|
if (patch.groupKey !== void 0) onChange({ groupField: patch.groupKey });
|
|
@@ -35333,7 +34884,7 @@ function ArchivedView({
|
|
|
35333
34884
|
const [loading, setLoading] = useState94(true);
|
|
35334
34885
|
const [error, setError] = useState94(null);
|
|
35335
34886
|
const [restoring, setRestoring] = useState94(null);
|
|
35336
|
-
const [
|
|
34887
|
+
const [refusal3, setRefusal] = useState94(null);
|
|
35337
34888
|
useEffect80(() => {
|
|
35338
34889
|
if (laneFromHost) setLane(laneFromHost);
|
|
35339
34890
|
}, [laneFromHost]);
|
|
@@ -35410,7 +34961,7 @@ function ArchivedView({
|
|
|
35410
34961
|
/* @__PURE__ */ jsxs106("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
35411
34962
|
/* @__PURE__ */ jsx116("span", { className: "truncate text-sm", children: recordName(row.document, titleKey) }),
|
|
35412
34963
|
/* @__PURE__ */ jsx116("span", { className: "truncate text-xs text-muted-foreground", "data-testid": "archived-who", children: archivedByLine(row) }),
|
|
35413
|
-
|
|
34964
|
+
refusal3 && refusal3.recordId === row.id ? /* @__PURE__ */ jsx116(RefusalNotice, { error: refusal3.error, className: "mt-2" }) : null
|
|
35414
34965
|
] }),
|
|
35415
34966
|
mayRestore ? /* @__PURE__ */ jsx116(
|
|
35416
34967
|
Button71,
|
|
@@ -35439,7 +34990,7 @@ function RetiredColumns({ tableId, mayRestore, whyNot }) {
|
|
|
35439
34990
|
const [rows, setRows] = useState94(null);
|
|
35440
34991
|
const [error, setError] = useState94(null);
|
|
35441
34992
|
const [restoring, setRestoring] = useState94(null);
|
|
35442
|
-
const [
|
|
34993
|
+
const [refusal3, setRefusal] = useState94(null);
|
|
35443
34994
|
const read = useCallback40(async () => {
|
|
35444
34995
|
const answer = await client.fieldsRetired({ table_id: tableId });
|
|
35445
34996
|
if (answer.ok) {
|
|
@@ -35483,7 +35034,7 @@ function RetiredColumns({ tableId, mayRestore, whyNot }) {
|
|
|
35483
35034
|
/* @__PURE__ */ jsxs106("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
35484
35035
|
/* @__PURE__ */ jsx116("span", { className: "truncate text-sm", children: name }),
|
|
35485
35036
|
/* @__PURE__ */ jsx116("span", { className: "truncate text-xs text-muted-foreground", children: retiredColumnLine(row) }),
|
|
35486
|
-
|
|
35037
|
+
refusal3 && refusal3.fieldId === row.id ? /* @__PURE__ */ jsx116(RefusalNotice, { error: refusal3.error, className: "mt-2" }) : null
|
|
35487
35038
|
] }),
|
|
35488
35039
|
mayRestore ? /* @__PURE__ */ jsx116(Button71, { size: "sm", variant: "outline", disabled: restoring === row.id, onClick: () => void restore(row.id), children: restoring === row.id ? "Bringing it back\u2026" : "Restore" }) : null
|
|
35489
35040
|
]
|
|
@@ -35552,7 +35103,7 @@ function ArchivedPortals({
|
|
|
35552
35103
|
const [confirming, setConfirming] = useState95(null);
|
|
35553
35104
|
const [typed2, setTyped] = useState95("");
|
|
35554
35105
|
const [restoring, setRestoring] = useState95(null);
|
|
35555
|
-
const [
|
|
35106
|
+
const [refusal3, setRefusal] = useState95(null);
|
|
35556
35107
|
const [said2, setSaid] = useState95(null);
|
|
35557
35108
|
const read = useCallback41(async () => {
|
|
35558
35109
|
const answered = await client.listPortals({ archived: "archived" });
|
|
@@ -35668,7 +35219,7 @@ function ArchivedPortals({
|
|
|
35668
35219
|
)
|
|
35669
35220
|
] })
|
|
35670
35221
|
] }) : null,
|
|
35671
|
-
|
|
35222
|
+
refusal3 && refusal3.portalId === portal.portal_id ? /* @__PURE__ */ jsx117(RefusalNotice, { error: refusal3.error }) : null
|
|
35672
35223
|
]
|
|
35673
35224
|
},
|
|
35674
35225
|
portal.portal_id
|
|
@@ -35702,10 +35253,10 @@ import { useTable as useTable20 } from "@ai-matrx/records/react";
|
|
|
35702
35253
|
var NOOP3 = () => {
|
|
35703
35254
|
};
|
|
35704
35255
|
function viewActions(whyNot, host) {
|
|
35705
|
-
const one = (
|
|
35706
|
-
if (whyNot !== null) return { ...
|
|
35707
|
-
if (!run) return { ...
|
|
35708
|
-
return { ...
|
|
35256
|
+
const one = (base2, run) => {
|
|
35257
|
+
if (whyNot !== null) return { ...base2, disabledReason: whyNot, run: NOOP3 };
|
|
35258
|
+
if (!run) return { ...base2, disabledReason: ACTION_NOT_HERE_REASON, run: NOOP3 };
|
|
35259
|
+
return { ...base2, run };
|
|
35709
35260
|
};
|
|
35710
35261
|
return [
|
|
35711
35262
|
one({ id: "rename", label: "Rename view\u2026", icon: "pencil", group: "organize", verb: "rename" }, host.rename),
|
|
@@ -35717,8 +35268,8 @@ function viewActions(whyNot, host) {
|
|
|
35717
35268
|
];
|
|
35718
35269
|
}
|
|
35719
35270
|
function copyName(name, taken) {
|
|
35720
|
-
const
|
|
35721
|
-
if (!taken.includes(
|
|
35271
|
+
const base2 = `${name} (copy)`;
|
|
35272
|
+
if (!taken.includes(base2)) return base2;
|
|
35722
35273
|
for (let n = 2; ; n += 1) {
|
|
35723
35274
|
const next = `${name} (copy ${n})`;
|
|
35724
35275
|
if (!taken.includes(next)) return next;
|
|
@@ -36490,7 +36041,7 @@ function MyChecklistSteps({
|
|
|
36490
36041
|
}, [held, onSteps]);
|
|
36491
36042
|
const steps = onlyIds ? held.filter((s) => onlyIds.has(s.step_id)) : held;
|
|
36492
36043
|
const [busy, setBusy] = useState98(null);
|
|
36493
|
-
const [
|
|
36044
|
+
const [refusal3, setRefusal] = useState98(null);
|
|
36494
36045
|
const complete = useCallback44(
|
|
36495
36046
|
async (step2, evidence) => {
|
|
36496
36047
|
setBusy(step2.step_id);
|
|
@@ -36513,7 +36064,7 @@ function MyChecklistSteps({
|
|
|
36513
36064
|
/* @__PURE__ */ jsx120("span", { className: "tabular-nums", children: steps.length })
|
|
36514
36065
|
] }),
|
|
36515
36066
|
error ? /* @__PURE__ */ jsx120(RefusalNotice, { error }) : null,
|
|
36516
|
-
|
|
36067
|
+
refusal3 ? /* @__PURE__ */ jsx120(RefusalNotice, { error: refusal3 }) : null,
|
|
36517
36068
|
/* @__PURE__ */ jsx120("ol", { className: "flex flex-col gap-1.5", children: steps.map(
|
|
36518
36069
|
(step2) => actions ? /* @__PURE__ */ jsxs110("div", { className: "flex flex-col gap-0.5", "data-step-row": step2.step_id, children: [
|
|
36519
36070
|
/* @__PURE__ */ jsx120(StepRow, { step: step2, busy: busy === step2.step_id, onComplete: (evidence) => void complete(step2, evidence) }),
|
|
@@ -36713,7 +36264,7 @@ function ChecklistTemplateEditor({
|
|
|
36713
36264
|
const [saved, setSaved] = useState98(false);
|
|
36714
36265
|
const [name, setName] = useState98("");
|
|
36715
36266
|
const [rows, setRows] = useState98([{ ...EMPTY_ROW }]);
|
|
36716
|
-
const [
|
|
36267
|
+
const [refusal3, setRefusal] = useState98(null);
|
|
36717
36268
|
const [error, setError] = useState98(null);
|
|
36718
36269
|
const [busy, setBusy] = useState98(false);
|
|
36719
36270
|
const [loading, setLoading] = useState98(Boolean(templateId));
|
|
@@ -36889,10 +36440,10 @@ function ChecklistTemplateEditor({
|
|
|
36889
36440
|
] }, index)) }),
|
|
36890
36441
|
/* @__PURE__ */ jsxs110("div", { className: "flex items-center gap-1.5", children: [
|
|
36891
36442
|
/* @__PURE__ */ jsx120(Button75, { size: "sm", variant: "outline", onClick: () => setRows((held) => [...held, { ...EMPTY_ROW }]), children: "Add a step" }),
|
|
36892
|
-
/* @__PURE__ */ jsx120(Button75, { size: "sm", disabled: busy ||
|
|
36443
|
+
/* @__PURE__ */ jsx120(Button75, { size: "sm", disabled: busy || refusal3 !== null || spec.steps.length === 0, onClick: () => void save(), children: busy ? "\u2026" : "Save" }),
|
|
36893
36444
|
saved && !busy ? /* @__PURE__ */ jsx120("span", { className: "text-xs text-muted-foreground", "data-testid": "checklist-editor-saved", role: "status", children: "Saved" }) : null
|
|
36894
36445
|
] }),
|
|
36895
|
-
|
|
36446
|
+
refusal3 ? /* @__PURE__ */ jsx120("p", { className: "text-xs text-muted-foreground", "data-testid": "checklist-editor-refusal", children: refusal3 }) : null
|
|
36896
36447
|
] });
|
|
36897
36448
|
}
|
|
36898
36449
|
function toStepSpec(row, index) {
|
|
@@ -42228,7 +41779,7 @@ function FormStage({
|
|
|
42228
41779
|
const [answers, setAnswers] = useState114(() => ({ ...initialAnswers ?? {} }));
|
|
42229
41780
|
const [at, setAt] = useState114(0);
|
|
42230
41781
|
const [error, setError] = useState114(null);
|
|
42231
|
-
const [
|
|
41782
|
+
const [refusal3, setRefusal] = useState114(null);
|
|
42232
41783
|
const [writing, setWriting] = useState114(false);
|
|
42233
41784
|
const [done, setDone] = useState114(null);
|
|
42234
41785
|
const [hidden, setHidden] = useState114({});
|
|
@@ -42601,10 +42152,10 @@ function FormStage({
|
|
|
42601
42152
|
) : null,
|
|
42602
42153
|
form.intro && index === 0 ? /* @__PURE__ */ jsx137("p", { className: "text-base text-muted-foreground", children: authored(host, form.intro, "form-intro") }) : null,
|
|
42603
42154
|
error ? /* @__PURE__ */ jsx137(RefusalNotice, { error, className: "text-left" }) : null,
|
|
42604
|
-
|
|
42155
|
+
refusal3 ? /* @__PURE__ */ jsx137(
|
|
42605
42156
|
RefusalNotice,
|
|
42606
42157
|
{
|
|
42607
|
-
error:
|
|
42158
|
+
error: refusal3,
|
|
42608
42159
|
className: "text-left",
|
|
42609
42160
|
onKeepEditing: () => {
|
|
42610
42161
|
setRefusal(null);
|
|
@@ -42799,11 +42350,11 @@ import {
|
|
|
42799
42350
|
formLookDocument
|
|
42800
42351
|
} from "@ai-matrx/records/forms";
|
|
42801
42352
|
import { Fragment as Fragment56, jsx as jsx138, jsxs as jsxs128 } from "react/jsx-runtime";
|
|
42802
|
-
function freshFormName(
|
|
42353
|
+
function freshFormName(base2, taken) {
|
|
42803
42354
|
const names = new Set(taken.map((n) => n.trim().toLowerCase()));
|
|
42804
|
-
if (!names.has(
|
|
42355
|
+
if (!names.has(base2.toLowerCase())) return base2;
|
|
42805
42356
|
for (let n = 2; ; n += 1) {
|
|
42806
|
-
const next = `${
|
|
42357
|
+
const next = `${base2} ${n}`;
|
|
42807
42358
|
if (!names.has(next.toLowerCase())) return next;
|
|
42808
42359
|
}
|
|
42809
42360
|
}
|
|
@@ -43100,8 +42651,8 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, startWithOne,
|
|
|
43100
42651
|
return;
|
|
43101
42652
|
}
|
|
43102
42653
|
setMakeOnMount("making");
|
|
43103
|
-
const
|
|
43104
|
-
void create(freshFormName(
|
|
42654
|
+
const base2 = table.data?.name?.trim() ? `${table.data.name.trim()} form` : "Form";
|
|
42655
|
+
void create(freshFormName(base2, forms.map((f) => f.name))).then(
|
|
43105
42656
|
(made) => setMakeOnMount(made ? "made" : "not-made")
|
|
43106
42657
|
);
|
|
43107
42658
|
}, [createOnMount, makeOnMount, forms, fields.data, create, table.data, table.error]);
|
|
@@ -45063,7 +44614,7 @@ function AddChart({ subject, onAdd, onClose }) {
|
|
|
45063
44614
|
const field2 = all.find((f) => f.key === key);
|
|
45064
44615
|
return field2 ? scalarText(field2, value, labels) : String(value);
|
|
45065
44616
|
};
|
|
45066
|
-
const [
|
|
44617
|
+
const [measureKey4, setMeasureKey] = useState121("count");
|
|
45067
44618
|
const [splitKey, setSplitKey] = useState121("none");
|
|
45068
44619
|
const [kind, setKind] = useState121("auto");
|
|
45069
44620
|
const [filter, setFilter] = useState121({});
|
|
@@ -45071,7 +44622,7 @@ function AddChart({ subject, onAdd, onClose }) {
|
|
|
45071
44622
|
const numbers = numberColumns(all);
|
|
45072
44623
|
const choices = offerableFields(all, "choice");
|
|
45073
44624
|
const dates = offerableFields(all, "date");
|
|
45074
|
-
const measure =
|
|
44625
|
+
const measure = measureKey4 === "count" ? { op: "count" } : { op: measureKey4.split(":")[0], key: measureKey4.split(":")[1] };
|
|
45075
44626
|
const split = splitKey === "none" ? { kind: "none" } : splitKey.startsWith("period:") ? { kind: "period", key: splitKey.split(":")[2], by: splitKey.split(":")[1] } : { kind: "column", key: splitKey.slice("column:".length) };
|
|
45076
44627
|
const shape = kind !== "auto" ? kind : split.kind === "period" ? "line" : split.kind === "column" ? "column" : "number";
|
|
45077
44628
|
function pickTable(next) {
|
|
@@ -45089,7 +44640,7 @@ function AddChart({ subject, onAdd, onClose }) {
|
|
|
45089
44640
|
return /* @__PURE__ */ jsxs135("div", { className: "flex flex-col gap-2 rounded border p-2 text-xs", role: "group", "aria-label": "Add chart", children: [
|
|
45090
44641
|
/* @__PURE__ */ jsxs135("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
45091
44642
|
/* @__PURE__ */ jsx146("div", { className: "min-w-[12rem]", children: /* @__PURE__ */ jsx146(TablePicker, { dataSource: client.config.dataSource, value: tableId, onChange: pickTable }) }),
|
|
45092
|
-
/* @__PURE__ */ jsxs135(Select17, { value:
|
|
44643
|
+
/* @__PURE__ */ jsxs135(Select17, { value: measureKey4, onValueChange: setMeasureKey, children: [
|
|
45093
44644
|
/* @__PURE__ */ jsx146(SelectTrigger17, { size: "sm", "aria-label": "What the chart counts", className: "h-7 min-w-[8rem] text-xs", children: /* @__PURE__ */ jsx146(SelectValue17, {}) }),
|
|
45094
44645
|
/* @__PURE__ */ jsxs135(SelectContent17, { children: [
|
|
45095
44646
|
/* @__PURE__ */ jsx146(SelectItem17, { value: "count", children: "How many" }),
|
|
@@ -45185,14 +44736,14 @@ function filterTargets(filter, blocks) {
|
|
|
45185
44736
|
if (filter.targets && filter.targets.length > 0) return filter.targets;
|
|
45186
44737
|
return blocks.filter((b) => b.kind === "list" && b.table_id === filter.table_id).map((b) => b.id);
|
|
45187
44738
|
}
|
|
45188
|
-
function combineFilter(
|
|
44739
|
+
function combineFilter(base2, extra, fieldIdOf) {
|
|
45189
44740
|
const extraKeys = Object.keys(extra);
|
|
45190
|
-
if (!
|
|
44741
|
+
if (!base2 || !isRuleFilter3(base2) && Object.keys(base2).length === 0) {
|
|
45191
44742
|
return { filter: extraKeys.length > 0 ? { ...extra } : null, dropped: [] };
|
|
45192
44743
|
}
|
|
45193
|
-
if (!isRuleFilter3(
|
|
44744
|
+
if (!isRuleFilter3(base2)) return { filter: { ...base2, ...extra }, dropped: [] };
|
|
45194
44745
|
const dropped = [];
|
|
45195
|
-
let rule =
|
|
44746
|
+
let rule = base2;
|
|
45196
44747
|
for (const key of extraKeys) {
|
|
45197
44748
|
const id = fieldIdOf(key);
|
|
45198
44749
|
if (!id) {
|
|
@@ -45848,372 +45399,9 @@ import { Badge as Badge24, BasicInput as BasicInput33, Button as Button97, Check
|
|
|
45848
45399
|
import { useFields as useFields31, useRecordsClient as useRecordsClient88 } from "@ai-matrx/records/react";
|
|
45849
45400
|
|
|
45850
45401
|
// src/question.ts
|
|
45851
|
-
|
|
45852
|
-
|
|
45853
|
-
|
|
45854
|
-
var QUESTION_LIMIT_DEFAULT = 25;
|
|
45855
|
-
var QUESTION_GROUP_CEILING = 200;
|
|
45856
|
-
var QUESTION_THROUGH_GROUP_CAP = 60;
|
|
45857
|
-
function newQuestion() {
|
|
45858
|
-
return { v: 1, measures: [{ op: "count" }], where: null, through: [], group: null, asOf: null, order: null, limit: QUESTION_LIMIT_DEFAULT, show: "table" };
|
|
45859
|
-
}
|
|
45860
|
-
function questionFromDefinition(definition) {
|
|
45861
|
-
const raw = definition && typeof definition === "object" ? definition.question : null;
|
|
45862
|
-
const base = newQuestion();
|
|
45863
|
-
if (!raw || typeof raw !== "object") return base;
|
|
45864
|
-
const measures = Array.isArray(raw.measures) ? raw.measures.filter((m) => !!m && QUESTION_OPS.includes(m.op)) : [];
|
|
45865
|
-
return {
|
|
45866
|
-
v: 1,
|
|
45867
|
-
measures: measures.length > 0 ? measures : base.measures,
|
|
45868
|
-
where: raw.where && typeof raw.where === "object" ? raw.where : null,
|
|
45869
|
-
through: Array.isArray(raw.through) ? raw.through.filter((t) => t && typeof t.relation === "string" && typeof t.key === "string") : [],
|
|
45870
|
-
group: raw.group && typeof raw.group === "object" && "kind" in raw.group ? raw.group : null,
|
|
45871
|
-
asOf: typeof raw.asOf === "string" && raw.asOf !== "" ? raw.asOf : null,
|
|
45872
|
-
order: raw.order && (raw.order.by === "measure" || raw.order.by === "count") ? raw.order : null,
|
|
45873
|
-
limit: typeof raw.limit === "number" && raw.limit > 0 ? Math.min(Math.floor(raw.limit), QUESTION_GROUP_CEILING) : base.limit,
|
|
45874
|
-
show: ["table", "bar", "column", "line", "donut", "number"].includes(raw.show) ? raw.show : base.show
|
|
45875
|
-
};
|
|
45876
|
-
}
|
|
45877
|
-
function refusal(message, hint) {
|
|
45878
|
-
return { ok: false, error: { code: "invalid_argument", message, ...hint ? { hint } : {} } };
|
|
45879
|
-
}
|
|
45880
|
-
function fieldById(fields, id) {
|
|
45881
|
-
return fields.find((f) => f.id === id);
|
|
45882
|
-
}
|
|
45883
|
-
function flatWhere(where, fields) {
|
|
45884
|
-
if (!where) return {};
|
|
45885
|
-
const node = where;
|
|
45886
|
-
const clauses = node.op === "and" ? node.args ?? [] : [where];
|
|
45887
|
-
const out = {};
|
|
45888
|
-
for (const clause of clauses) {
|
|
45889
|
-
const c = clause;
|
|
45890
|
-
if (c.op !== "eq" || !c.args?.[0]?.field || !c.args[1] || !("const" in c.args[1])) return null;
|
|
45891
|
-
const f = fieldById(fields, c.args[0].field);
|
|
45892
|
-
if (!f) return null;
|
|
45893
|
-
out[f.key] = c.args[1].const;
|
|
45894
|
-
}
|
|
45895
|
-
return out;
|
|
45896
|
-
}
|
|
45897
|
-
function isFormula(fields, key) {
|
|
45898
|
-
if (!key) return false;
|
|
45899
|
-
const f = fields.find((x) => x.key === key);
|
|
45900
|
-
return !!f && (f.type === "formula" || editorKindFor(f) === "formula");
|
|
45901
|
-
}
|
|
45902
|
-
function rowsOf2(rows, groupKey, keys) {
|
|
45903
|
-
return rows.map((r) => {
|
|
45904
|
-
const values = {};
|
|
45905
|
-
for (const k of keys) {
|
|
45906
|
-
const v = (r.measures ?? {})[k];
|
|
45907
|
-
values[k] = v === null || v === void 0 ? null : Number(v);
|
|
45908
|
-
}
|
|
45909
|
-
const withheld = {};
|
|
45910
|
-
for (const [name, notice] of Object.entries(r.withheld ?? {})) if (keys.includes(name)) withheld[name] = notice;
|
|
45911
|
-
const g = groupKey ? (r.groups ?? {})[groupKey] : null;
|
|
45912
|
-
return { group: g === null || g === void 0 ? null : String(g), values, withheld, n: Number(r.row_count ?? 0) };
|
|
45913
|
-
});
|
|
45914
|
-
}
|
|
45915
|
-
function sortAndCut(rows, spec, keys) {
|
|
45916
|
-
const first = keys[0];
|
|
45917
|
-
const by = spec.order?.by ?? "count";
|
|
45918
|
-
const dir = spec.order?.direction ?? "desc";
|
|
45919
|
-
const value = (r) => by === "count" ? r.n : first ? r.values[first] : null;
|
|
45920
|
-
const present = rows.filter((r) => value(r) !== null && value(r) !== void 0);
|
|
45921
|
-
const blank = rows.filter((r) => value(r) === null || value(r) === void 0);
|
|
45922
|
-
present.sort((a, b) => dir === "desc" ? value(b) - value(a) : value(a) - value(b));
|
|
45923
|
-
return [...present, ...blank];
|
|
45924
|
-
}
|
|
45925
|
-
async function askQuestion(client, tableId, spec, fields) {
|
|
45926
|
-
const measures = spec.measures.length > 0 ? spec.measures : [{ op: "count" }];
|
|
45927
|
-
for (const m of measures) {
|
|
45928
|
-
if (m.op !== "count" && !m.key) return refusal(`Pick the column to ${m.op === "avg" ? "average" : m.op}.`);
|
|
45929
|
-
}
|
|
45930
|
-
const keys = measures.map((m) => measureKey4({ op: m.op, ...m.key ? { key: m.key } : {} }));
|
|
45931
|
-
const group = spec.group;
|
|
45932
|
-
if (spec.asOf) return askAsOf(client, tableId, spec, fields, measures, keys);
|
|
45933
|
-
let filter = spec.where ?? {};
|
|
45934
|
-
if (spec.through.length > 0) {
|
|
45935
|
-
const flat = flatWhere(spec.where, fields);
|
|
45936
|
-
if (flat === null) {
|
|
45937
|
-
return refusal(
|
|
45938
|
-
"A condition on a related table can only be joined with \u201Cis\u201D conditions, all of them true.",
|
|
45939
|
-
"Simplify the other conditions, or move them to the related table."
|
|
45940
|
-
);
|
|
45941
|
-
}
|
|
45942
|
-
for (const t of spec.through) flat[`${t.relation}.${t.key}`] = t.value;
|
|
45943
|
-
filter = flat;
|
|
45944
|
-
}
|
|
45945
|
-
if (group?.kind === "through") return askThrough(client, tableId, spec, fields, measures, keys, filter);
|
|
45946
|
-
const ordered = measures.map((m, i) => {
|
|
45947
|
-
const one = { op: m.op, ...m.key ? { key: m.key } : {} };
|
|
45948
|
-
if (i === 0 && spec.order?.by === "measure") one["order"] = spec.order.direction;
|
|
45949
|
-
return one;
|
|
45950
|
-
});
|
|
45951
|
-
if (spec.order?.by === "count") {
|
|
45952
|
-
const at = measures.findIndex((m) => m.op === "count");
|
|
45953
|
-
if (at >= 0) ordered[at]["order"] = spec.order.direction;
|
|
45954
|
-
else ordered.unshift({ op: "count", order: spec.order.direction });
|
|
45955
|
-
}
|
|
45956
|
-
const groupBy = group?.kind === "field" ? [group.key] : [];
|
|
45957
|
-
const bucket = group?.kind === "bucket" ? { key: group.key, by: group.by } : null;
|
|
45958
|
-
const groupKey = group?.kind === "field" ? group.key : group?.kind === "bucket" ? `${group.key}_${group.by}` : null;
|
|
45959
|
-
const limit = group ? Math.max(1, Math.min(spec.limit, QUESTION_GROUP_CEILING)) : 1;
|
|
45960
|
-
const asked2 = await client.recordAggregate({
|
|
45961
|
-
table_id: tableId,
|
|
45962
|
-
groupBy,
|
|
45963
|
-
// `order` rides the measure into custom.agg_sql (VISION-REACH W2); the type predates it.
|
|
45964
|
-
measures: ordered,
|
|
45965
|
-
bucket,
|
|
45966
|
-
filter,
|
|
45967
|
-
limit
|
|
45968
|
-
});
|
|
45969
|
-
if (!asked2.ok) return asked2;
|
|
45970
|
-
const rows = rowsOf2(asked2.data, groupKey, keys);
|
|
45971
|
-
let groupsTotal = group ? rows.length : null;
|
|
45972
|
-
let groupsExact = true;
|
|
45973
|
-
if (group && rows.length >= limit && limit < QUESTION_GROUP_CEILING) {
|
|
45974
|
-
const every = await client.recordAggregate({
|
|
45975
|
-
table_id: tableId,
|
|
45976
|
-
groupBy,
|
|
45977
|
-
measures: [{ op: "count" }],
|
|
45978
|
-
bucket,
|
|
45979
|
-
filter,
|
|
45980
|
-
limit: QUESTION_GROUP_CEILING
|
|
45981
|
-
});
|
|
45982
|
-
if (every.ok) {
|
|
45983
|
-
groupsTotal = every.data.length;
|
|
45984
|
-
groupsExact = every.data.length < QUESTION_GROUP_CEILING;
|
|
45985
|
-
} else {
|
|
45986
|
-
groupsExact = false;
|
|
45987
|
-
}
|
|
45988
|
-
} else if (group && rows.length >= QUESTION_GROUP_CEILING) {
|
|
45989
|
-
groupsExact = false;
|
|
45990
|
-
}
|
|
45991
|
-
return {
|
|
45992
|
-
ok: true,
|
|
45993
|
-
data: {
|
|
45994
|
-
rows,
|
|
45995
|
-
measures: keys,
|
|
45996
|
-
groupKey,
|
|
45997
|
-
groupsTotal,
|
|
45998
|
-
groupsExact,
|
|
45999
|
-
truncated: groupsTotal !== null && (groupsTotal > rows.length || !groupsExact),
|
|
46000
|
-
asOf: null
|
|
46001
|
-
}
|
|
46002
|
-
};
|
|
46003
|
-
}
|
|
46004
|
-
async function askThrough(client, tableId, spec, fields, measures, keys, filter) {
|
|
46005
|
-
const group = spec.group;
|
|
46006
|
-
const rel = fields.find((f) => f.key === group.relation);
|
|
46007
|
-
if (!rel || !rel.relation_target) return refusal(`\u201C${group.relation}\u201D is not a relation of this table.`);
|
|
46008
|
-
const flat = filter && !filter.op ? filter : flatWhere(filter, fields);
|
|
46009
|
-
if (flat === null) {
|
|
46010
|
-
return refusal(
|
|
46011
|
-
"Summarizing by a related table's column can only be joined with \u201Cis\u201D conditions, all of them true.",
|
|
46012
|
-
"Simplify the conditions, or summarize by a column of this table."
|
|
46013
|
-
);
|
|
46014
|
-
}
|
|
46015
|
-
const values = await client.recordAggregate({
|
|
46016
|
-
table_id: rel.relation_target,
|
|
46017
|
-
groupBy: [group.key],
|
|
46018
|
-
measures: [{ op: "count" }],
|
|
46019
|
-
limit: QUESTION_THROUGH_GROUP_CAP + 1
|
|
46020
|
-
});
|
|
46021
|
-
if (!values.ok) return values;
|
|
46022
|
-
const named = values.data.map((r) => (r.groups ?? {})[group.key] ?? null).filter((v) => v !== null && v !== "");
|
|
46023
|
-
if (named.length > QUESTION_THROUGH_GROUP_CAP) {
|
|
46024
|
-
return refusal(
|
|
46025
|
-
`That column has more than ${QUESTION_THROUGH_GROUP_CAP} values, too many to summarize by.`,
|
|
46026
|
-
"Add a condition that narrows it, or summarize by a column of this table."
|
|
46027
|
-
);
|
|
46028
|
-
}
|
|
46029
|
-
const answered = [];
|
|
46030
|
-
for (let i = 0; i < named.length; i += 8) {
|
|
46031
|
-
const batch = await Promise.all(
|
|
46032
|
-
named.slice(i, i + 8).map(async (value) => {
|
|
46033
|
-
const one = await client.recordAggregate({
|
|
46034
|
-
table_id: tableId,
|
|
46035
|
-
groupBy: [],
|
|
46036
|
-
measures: measures.map((m) => ({ op: m.op, ...m.key ? { key: m.key } : {} })),
|
|
46037
|
-
filter: { ...flat, [`${group.relation}.${group.key}`]: value },
|
|
46038
|
-
limit: 1
|
|
46039
|
-
});
|
|
46040
|
-
return { value, one };
|
|
46041
|
-
})
|
|
46042
|
-
);
|
|
46043
|
-
for (const { value, one } of batch) {
|
|
46044
|
-
if (!one.ok) return one;
|
|
46045
|
-
const [row] = rowsOf2(one.data, null, keys);
|
|
46046
|
-
if (row && row.n > 0) answered.push({ ...row, group: value });
|
|
46047
|
-
}
|
|
46048
|
-
}
|
|
46049
|
-
const sorted = sortAndCut(answered, spec, keys);
|
|
46050
|
-
const limit = Math.max(1, Math.min(spec.limit, QUESTION_GROUP_CEILING));
|
|
46051
|
-
return {
|
|
46052
|
-
ok: true,
|
|
46053
|
-
data: {
|
|
46054
|
-
rows: sorted.slice(0, limit),
|
|
46055
|
-
measures: keys,
|
|
46056
|
-
groupKey: `${group.relation}.${group.key}`,
|
|
46057
|
-
groupsTotal: sorted.length,
|
|
46058
|
-
groupsExact: true,
|
|
46059
|
-
truncated: sorted.length > limit,
|
|
46060
|
-
asOf: null
|
|
46061
|
-
}
|
|
46062
|
-
};
|
|
46063
|
-
}
|
|
46064
|
-
async function askAsOf(client, tableId, spec, fields, measures, keys) {
|
|
46065
|
-
const group = spec.group;
|
|
46066
|
-
if (spec.through.length > 0 || group?.kind === "through") {
|
|
46067
|
-
return refusal("\u201CAs of\u201D cannot reach across a relation yet.", "Ask without the related table's column, or without \u201Cas of\u201D.");
|
|
46068
|
-
}
|
|
46069
|
-
if (group?.kind === "bucket") {
|
|
46070
|
-
return refusal("\u201CAs of\u201D cannot cut dates into periods yet.", "Summarize by the date itself, or ask without \u201Cas of\u201D.");
|
|
46071
|
-
}
|
|
46072
|
-
const match = flatWhere(spec.where, fields);
|
|
46073
|
-
if (match === null) {
|
|
46074
|
-
return refusal("\u201CAs of\u201D can only be filtered with \u201Cis\u201D conditions, all of them true.", "Simplify the filter, or ask without \u201Cas of\u201D.");
|
|
46075
|
-
}
|
|
46076
|
-
const formula = [...measures.map((m) => m.key), group?.key, ...Object.keys(match)].find((k) => isFormula(fields, k));
|
|
46077
|
-
if (formula) {
|
|
46078
|
-
const f = fields.find((x) => x.key === formula);
|
|
46079
|
-
return refusal(
|
|
46080
|
-
`${f?.label || formula} is worked out when a record is read, so it cannot be measured as of a moment.`,
|
|
46081
|
-
"Measure a stored column, or ask without \u201Cas of\u201D."
|
|
46082
|
-
);
|
|
46083
|
-
}
|
|
46084
|
-
const moment = new Date(spec.asOf);
|
|
46085
|
-
if (Number.isNaN(moment.getTime())) return refusal("\u201CAs of\u201D is not a date and time.");
|
|
46086
|
-
const config = client.config;
|
|
46087
|
-
const groupKey = group?.kind === "field" ? group.key : null;
|
|
46088
|
-
const byGroup = /* @__PURE__ */ new Map();
|
|
46089
|
-
for (let i = 0; i < measures.length; i++) {
|
|
46090
|
-
const m = measures[i];
|
|
46091
|
-
const response = await config.dataSource.rpc(
|
|
46092
|
-
"record_aggregate_as_of",
|
|
46093
|
-
{
|
|
46094
|
-
p_organization_id: config.organizationId,
|
|
46095
|
-
p_table_id: tableId,
|
|
46096
|
-
p_recorded_at: moment.toISOString(),
|
|
46097
|
-
p_measure: m.op,
|
|
46098
|
-
p_field_key: m.key ?? null,
|
|
46099
|
-
p_group_by: groupKey,
|
|
46100
|
-
p_match: match
|
|
46101
|
-
},
|
|
46102
|
-
{ schema: config.schema ?? "custom" }
|
|
46103
|
-
);
|
|
46104
|
-
if (response.error) return { ok: false, error: mapPgError3(response.error, "askQuestion.asOf") };
|
|
46105
|
-
const rows2 = Array.isArray(response.data) ? response.data : [];
|
|
46106
|
-
const bad = rows2.find((r) => Number(r.not_numbers ?? 0) > 0);
|
|
46107
|
-
if (bad && m.op !== "count") {
|
|
46108
|
-
return refusal(`${m.key} held \u201C${bad.a_non_number}\u201D then, which is not a number, so its ${m.op} cannot be worked out.`);
|
|
46109
|
-
}
|
|
46110
|
-
for (const r of rows2) {
|
|
46111
|
-
const g = groupKey ? r.bucket ?? null : null;
|
|
46112
|
-
const at = g ?? "\0all";
|
|
46113
|
-
const row = byGroup.get(at) ?? { group: g, values: {}, withheld: {}, n: Number(r.row_count ?? 0) };
|
|
46114
|
-
row.values[keys[i]] = m.op === "count" ? Number(r.row_count ?? 0) : r.result === null ? null : Number(r.result);
|
|
46115
|
-
byGroup.set(at, row);
|
|
46116
|
-
}
|
|
46117
|
-
}
|
|
46118
|
-
let rows = [...byGroup.values()];
|
|
46119
|
-
if (!groupKey && rows.length === 0) {
|
|
46120
|
-
rows = [{ group: null, values: Object.fromEntries(keys.map((k, i) => [k, measures[i].op === "count" ? 0 : null])), withheld: {}, n: 0 }];
|
|
46121
|
-
}
|
|
46122
|
-
for (const r of rows) for (const k of keys) if (!(k in r.values)) r.values[k] = null;
|
|
46123
|
-
const sorted = groupKey ? sortAndCut(rows, spec, keys) : rows;
|
|
46124
|
-
const limit = groupKey ? Math.max(1, Math.min(spec.limit, QUESTION_GROUP_CEILING)) : 1;
|
|
46125
|
-
return {
|
|
46126
|
-
ok: true,
|
|
46127
|
-
data: {
|
|
46128
|
-
rows: sorted.slice(0, limit),
|
|
46129
|
-
measures: keys,
|
|
46130
|
-
groupKey,
|
|
46131
|
-
groupsTotal: groupKey ? sorted.length : null,
|
|
46132
|
-
groupsExact: true,
|
|
46133
|
-
truncated: groupKey ? sorted.length > limit : false,
|
|
46134
|
-
asOf: moment.toISOString()
|
|
46135
|
-
}
|
|
46136
|
-
};
|
|
46137
|
-
}
|
|
46138
|
-
async function unreadableKeys(client, tableId, fields) {
|
|
46139
|
-
const guarded = fields.filter((f) => f.sensitivity === "confidential" || f.sensitivity === "restricted");
|
|
46140
|
-
const out = /* @__PURE__ */ new Set();
|
|
46141
|
-
if (guarded.length === 0) return out;
|
|
46142
|
-
const asked2 = await client.recordAggregate({
|
|
46143
|
-
table_id: tableId,
|
|
46144
|
-
groupBy: [],
|
|
46145
|
-
measures: guarded.map((f) => ({ op: "filled", key: f.key })),
|
|
46146
|
-
limit: 1
|
|
46147
|
-
});
|
|
46148
|
-
if (!asked2.ok) {
|
|
46149
|
-
for (const f of guarded) {
|
|
46150
|
-
const one = await client.recordAggregate({ table_id: tableId, groupBy: [], measures: [{ op: "filled", key: f.key }], limit: 1 });
|
|
46151
|
-
if (!one.ok || Object.keys(one.data[0]?.withheld ?? {}).length > 0) out.add(f.key);
|
|
46152
|
-
}
|
|
46153
|
-
return out;
|
|
46154
|
-
}
|
|
46155
|
-
for (const f of guarded) if (asked2.data.some((r) => r.withheld && `filled_${f.key}` in r.withheld)) out.add(f.key);
|
|
46156
|
-
return out;
|
|
46157
|
-
}
|
|
46158
|
-
function measurableFields(fields, op2) {
|
|
46159
|
-
if (op2 === "count") return [];
|
|
46160
|
-
return fields.filter((f) => isNumericField(f) || (op2 === "min" || op2 === "max") && editorKindFor(f) === "datetime");
|
|
46161
|
-
}
|
|
46162
|
-
var QUESTION_SURFACE = "custom/records/question";
|
|
46163
|
-
function savedOf(row) {
|
|
46164
|
-
return {
|
|
46165
|
-
id: row["id"],
|
|
46166
|
-
name: String(row["name"] ?? ""),
|
|
46167
|
-
spec: questionFromDefinition(row["definition"]),
|
|
46168
|
-
shared: row["visibility"] !== "personal",
|
|
46169
|
-
version: Number(row["version"] ?? 1),
|
|
46170
|
-
createdBy: row["created_by"] ?? null
|
|
46171
|
-
};
|
|
46172
|
-
}
|
|
46173
|
-
async function questionsOf(client, tableId) {
|
|
46174
|
-
const response = await client.config.dataSource.schema("platform").from("saved_view").select("id, name, definition, visibility, version, created_by").eq("surface_key", QUESTION_SURFACE).eq("subject_id", tableId).is("deleted_at", null).order("name", { ascending: true });
|
|
46175
|
-
if (response.error) return { ok: false, error: mapPgError3(response.error, "questionsOf") };
|
|
46176
|
-
const me = client.config.actor?.user_id ?? null;
|
|
46177
|
-
return {
|
|
46178
|
-
ok: true,
|
|
46179
|
-
data: (response.data ?? []).map(savedOf).filter((q) => q.shared || me !== null && q.createdBy === me)
|
|
46180
|
-
};
|
|
46181
|
-
}
|
|
46182
|
-
async function questionSave(client, args) {
|
|
46183
|
-
const name = args.name.trim();
|
|
46184
|
-
if (!name) return refusal("Name the question so the team can find it.");
|
|
46185
|
-
const response = await client.config.dataSource.rpc(
|
|
46186
|
-
"saved_view_save",
|
|
46187
|
-
{
|
|
46188
|
-
p_surface_key: QUESTION_SURFACE,
|
|
46189
|
-
p_id: args.id ?? null,
|
|
46190
|
-
p_subject_id: args.tableId,
|
|
46191
|
-
p_organization_id: client.config.organizationId,
|
|
46192
|
-
p_name: name,
|
|
46193
|
-
p_definition: { question: args.spec },
|
|
46194
|
-
p_visibility: args.shared ? "internal" : "personal",
|
|
46195
|
-
p_touch: true,
|
|
46196
|
-
...args.expectedVersion !== void 0 ? { p_expected_version: args.expectedVersion } : {}
|
|
46197
|
-
},
|
|
46198
|
-
{ schema: "public" }
|
|
46199
|
-
);
|
|
46200
|
-
if (response.error) {
|
|
46201
|
-
if (response.error.code === "23505") {
|
|
46202
|
-
return { ok: false, error: { code: "already_exists", message: `You already have a question called \u201C${name}\u201D.` } };
|
|
46203
|
-
}
|
|
46204
|
-
return { ok: false, error: mapPgError3(response.error, "questionSave") };
|
|
46205
|
-
}
|
|
46206
|
-
return { ok: true, data: response.data ? savedOf(response.data) : null };
|
|
46207
|
-
}
|
|
46208
|
-
async function questionArchive(client, id, version) {
|
|
46209
|
-
const response = await client.config.dataSource.rpc(
|
|
46210
|
-
"saved_view_archive",
|
|
46211
|
-
{ p_surface_key: QUESTION_SURFACE, p_id: id, ...version !== void 0 ? { p_expected_version: version } : {} },
|
|
46212
|
-
{ schema: "public" }
|
|
46213
|
-
);
|
|
46214
|
-
if (response.error) return { ok: false, error: mapPgError3(response.error, "questionArchive") };
|
|
46215
|
-
return { ok: true, data: response.data !== null };
|
|
46216
|
-
}
|
|
45402
|
+
var question_exports = {};
|
|
45403
|
+
__reExport(question_exports, questions_star);
|
|
45404
|
+
import * as questions_star from "@ai-matrx/records/questions";
|
|
46217
45405
|
|
|
46218
45406
|
// src/QuestionPanel.tsx
|
|
46219
45407
|
import { Fragment as Fragment59, jsx as jsx148, jsxs as jsxs137 } from "react/jsx-runtime";
|
|
@@ -46269,12 +45457,12 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46269
45457
|
}
|
|
46270
45458
|
let live = true;
|
|
46271
45459
|
void (async () => {
|
|
46272
|
-
const mine2 = await unreadableKeys(client, tableId, all);
|
|
45460
|
+
const mine2 = await (0, question_exports.unreadableKeys)(client, tableId, all);
|
|
46273
45461
|
const out = {};
|
|
46274
45462
|
for (const rel of all.filter((f) => editorKindFor(f) === "relation" && f.relation_target && !mine2.has(f.key))) {
|
|
46275
45463
|
const target = await client.fields({ table_id: rel.relation_target });
|
|
46276
45464
|
if (!target.ok) continue;
|
|
46277
|
-
const theirs = await unreadableKeys(client, rel.relation_target, target.data);
|
|
45465
|
+
const theirs = await (0, question_exports.unreadableKeys)(client, rel.relation_target, target.data);
|
|
46278
45466
|
out[rel.key] = { relation: rel, fields: target.data.filter((f) => !theirs.has(f.key) && editorKindFor(f) !== "relation") };
|
|
46279
45467
|
}
|
|
46280
45468
|
if (!live) return;
|
|
@@ -46289,7 +45477,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46289
45477
|
const [saved, setSaved] = useState123(null);
|
|
46290
45478
|
const [savedEpoch, setSavedEpoch] = useState123(0);
|
|
46291
45479
|
const [current, setCurrent] = useState123(null);
|
|
46292
|
-
const [spec, setSpec] = useState123(newQuestion);
|
|
45480
|
+
const [spec, setSpec] = useState123(question_exports.newQuestion);
|
|
46293
45481
|
const [name, setName] = useState123("");
|
|
46294
45482
|
const [shared, setShared] = useState123(true);
|
|
46295
45483
|
const [saveError, setSaveError] = useState123(null);
|
|
@@ -46298,7 +45486,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46298
45486
|
const openedFromLink = useRef59(false);
|
|
46299
45487
|
useEffect107(() => {
|
|
46300
45488
|
let live = true;
|
|
46301
|
-
void questionsOf(client, tableId).then((answer2) => {
|
|
45489
|
+
void (0, question_exports.questionsOf)(client, tableId).then((answer2) => {
|
|
46302
45490
|
if (!live) return;
|
|
46303
45491
|
setSaved(answer2.ok ? answer2.data : []);
|
|
46304
45492
|
if (answer2.ok && activeQuestionId && !openedFromLink.current) {
|
|
@@ -46314,7 +45502,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46314
45502
|
}, [client, tableId, savedEpoch, activeQuestionId]);
|
|
46315
45503
|
const open = (q) => {
|
|
46316
45504
|
setCurrent(q);
|
|
46317
|
-
setSpec(q ? q.spec : newQuestion());
|
|
45505
|
+
setSpec(q ? q.spec : (0, question_exports.newQuestion)());
|
|
46318
45506
|
setName(q ? q.name : "");
|
|
46319
45507
|
setShared(q ? q.shared : true);
|
|
46320
45508
|
setSaveError(null);
|
|
@@ -46333,7 +45521,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46333
45521
|
let live = true;
|
|
46334
45522
|
setAsking(true);
|
|
46335
45523
|
const t = setTimeout(() => {
|
|
46336
|
-
void askQuestion(client, tableId, spec, all).then((a) => {
|
|
45524
|
+
void (0, question_exports.askQuestion)(client, tableId, spec, all).then((a) => {
|
|
46337
45525
|
if (!live) return;
|
|
46338
45526
|
setAnswer(a);
|
|
46339
45527
|
setAsking(false);
|
|
@@ -46349,7 +45537,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46349
45537
|
setSaving(true);
|
|
46350
45538
|
setSaveError(null);
|
|
46351
45539
|
const editing = !asNew && current && mine;
|
|
46352
|
-
const kept = await questionSave(client, {
|
|
45540
|
+
const kept = await (0, question_exports.questionSave)(client, {
|
|
46353
45541
|
...editing ? { id: current.id, expectedVersion: current.version } : {},
|
|
46354
45542
|
tableId,
|
|
46355
45543
|
name: asNew && current && name.trim() === current.name ? `${name.trim()} (copy)` : name,
|
|
@@ -46367,7 +45555,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46367
45555
|
};
|
|
46368
45556
|
const archive = async () => {
|
|
46369
45557
|
if (!current) return;
|
|
46370
|
-
const gone = await questionArchive(client, current.id, current.version);
|
|
45558
|
+
const gone = await (0, question_exports.questionArchive)(client, current.id, current.version);
|
|
46371
45559
|
if (!gone.ok) return setSaveError(gone.error);
|
|
46372
45560
|
open(null);
|
|
46373
45561
|
setSavedEpoch((n) => n + 1);
|
|
@@ -46522,17 +45710,17 @@ function Measures({ measures, fields, onChange }) {
|
|
|
46522
45710
|
const set = (i, next) => onChange(measures.map((m, j) => j === i ? next : m));
|
|
46523
45711
|
return /* @__PURE__ */ jsxs137("div", { className: "flex flex-col gap-1", children: [
|
|
46524
45712
|
measures.map((m, i) => {
|
|
46525
|
-
const eligible = measurableFields(fields, m.op);
|
|
45713
|
+
const eligible = (0, question_exports.measurableFields)(fields, m.op);
|
|
46526
45714
|
return /* @__PURE__ */ jsxs137("div", { className: "flex items-center gap-1", "data-testid": "question-measure", children: [
|
|
46527
45715
|
/* @__PURE__ */ jsx148(
|
|
46528
45716
|
PickOne,
|
|
46529
45717
|
{
|
|
46530
45718
|
label: "Measure",
|
|
46531
45719
|
value: m.op,
|
|
46532
|
-
options: QUESTION_OPS.map((op2) => ({ value: op2, label: OP_LABEL[op2] })),
|
|
45720
|
+
options: question_exports.QUESTION_OPS.map((op2) => ({ value: op2, label: OP_LABEL[op2] })),
|
|
46533
45721
|
onChange: (op2) => {
|
|
46534
45722
|
const nextOp = op2;
|
|
46535
|
-
const keep = nextOp !== "count" && measurableFields(fields, nextOp).some((f) => f.key === m.key);
|
|
45723
|
+
const keep = nextOp !== "count" && (0, question_exports.measurableFields)(fields, nextOp).some((f) => f.key === m.key);
|
|
46536
45724
|
set(i, nextOp === "count" ? { op: "count" } : { op: nextOp, ...keep ? { key: m.key } : {} });
|
|
46537
45725
|
},
|
|
46538
45726
|
className: "w-28",
|
|
@@ -46964,14 +46152,14 @@ function questionFromWords(text, fields, choices = {}) {
|
|
|
46964
46152
|
const measured = head === "" ? null : columnNamed2(head, names);
|
|
46965
46153
|
if (op2 === null) {
|
|
46966
46154
|
if (head === "") op2 = "count";
|
|
46967
|
-
else if (measured && measurableFields([...fields], "sum").some((f) => f.key === measured.key)) op2 = "sum";
|
|
46155
|
+
else if (measured && (0, question_exports.measurableFields)([...fields], "sum").some((f) => f.key === measured.key)) op2 = "sum";
|
|
46968
46156
|
else return { ok: false, why: "Start with count, sum, average, smallest or largest" };
|
|
46969
46157
|
}
|
|
46970
|
-
const spec = { ...newQuestion(), group };
|
|
46158
|
+
const spec = { ...(0, question_exports.newQuestion)(), group };
|
|
46971
46159
|
let measureReads = "Count";
|
|
46972
46160
|
if (op2 !== "count") {
|
|
46973
46161
|
if (!measured) return { ok: false, why: head === "" ? `${OP_READS[op2]} which column?` : `No column named \u201C${head}\u201D` };
|
|
46974
|
-
if (!measurableFields([...fields], op2).some((f) => f.key === measured.key)) {
|
|
46162
|
+
if (!(0, question_exports.measurableFields)([...fields], op2).some((f) => f.key === measured.key)) {
|
|
46975
46163
|
return { ok: false, why: `${fieldName(measured)} is not a number column` };
|
|
46976
46164
|
}
|
|
46977
46165
|
spec.measures = [{ op: op2, key: measured.key }];
|
|
@@ -47008,7 +46196,7 @@ function TableAsk({ tableId, onOpenInQuestions }) {
|
|
|
47008
46196
|
const read = questionFromWords(words2, all, choices);
|
|
47009
46197
|
if (!read.ok) return setSaid({ kind: "not-read", why: read.why });
|
|
47010
46198
|
setSaid({ kind: "asking", reads: read.reads });
|
|
47011
|
-
const answered = await askQuestion(client, tableId, read.spec, all);
|
|
46199
|
+
const answered = await (0, question_exports.askQuestion)(client, tableId, read.spec, all);
|
|
47012
46200
|
setSaid(answered.ok ? { kind: "answer", reads: read.reads, spec: read.spec, answer: answered.data } : { kind: "refused", error: answered.error });
|
|
47013
46201
|
};
|
|
47014
46202
|
return /* @__PURE__ */ jsxs138(Popover14, { open, onOpenChange: setOpen, children: [
|
|
@@ -49608,16 +48796,16 @@ function toolbarFold(input) {
|
|
|
49608
48796
|
};
|
|
49609
48797
|
const withGap = (width) => width > 0 ? width + gap : 0;
|
|
49610
48798
|
const shareNow = input.share ? withGap(input.share.now) : 0;
|
|
49611
|
-
const
|
|
48799
|
+
const base2 = pieces.reduce((rest, p) => rest - withGap(p.piece.now), needsNow - shareNow);
|
|
49612
48800
|
const stages = input.tools ? [0, 1, 2, 3] : [0, 1, 2];
|
|
49613
48801
|
const shareOn = input.share ? withGap(input.share.full ?? input.share.now) : 0;
|
|
49614
|
-
const needs = stages.map((fold) => pieces.reduce((sum, p) => sum + withGap(widthAt(p, fold)),
|
|
48802
|
+
const needs = stages.map((fold) => pieces.reduce((sum, p) => sum + withGap(widthAt(p, fold)), base2 + shareOn));
|
|
49615
48803
|
const fits = needs.findIndex((need) => need <= available + 0.5);
|
|
49616
48804
|
if (fits >= 0) return stages[fits];
|
|
49617
48805
|
const least = Math.min(...needs);
|
|
49618
48806
|
const most = stages[needs.findIndex((need) => need <= least + 0.5)];
|
|
49619
48807
|
if (!input.tools || !input.share) return most;
|
|
49620
|
-
const fixed = pieces.reduce((sum, p) => sum + withGap(p.stage === 3 ? SLOT_MIN : widthAt(p, 3)),
|
|
48808
|
+
const fixed = pieces.reduce((sum, p) => sum + withGap(p.stage === 3 ? SLOT_MIN : widthAt(p, 3)), base2 + shareOn);
|
|
49621
48809
|
return fixed > available + 0.5 ? 4 : most;
|
|
49622
48810
|
}
|
|
49623
48811
|
function naturalWidth(el) {
|
|
@@ -49774,7 +48962,7 @@ function useSlotScroll(slot) {
|
|
|
49774
48962
|
}
|
|
49775
48963
|
|
|
49776
48964
|
// src/TablePage.tsx
|
|
49777
|
-
import { isUuidShape as
|
|
48965
|
+
import { isUuidShape as isUuidShape3 } from "@ai-matrx/kit/uuid";
|
|
49778
48966
|
import { Fragment as Fragment68, jsx as jsx163, jsxs as jsxs152 } from "react/jsx-runtime";
|
|
49779
48967
|
var RAIL_TITLE = {
|
|
49780
48968
|
settings: "Table settings",
|
|
@@ -49861,7 +49049,7 @@ function TableNotHere({
|
|
|
49861
49049
|
const client = useRecordsClient98();
|
|
49862
49050
|
const [archived, setArchived] = useState138({ phase: "asking" });
|
|
49863
49051
|
const [restoring, setRestoring] = useState138(false);
|
|
49864
|
-
const [
|
|
49052
|
+
const [refusal3, setRefusal] = useState138(null);
|
|
49865
49053
|
useEffect117(() => {
|
|
49866
49054
|
let alive = true;
|
|
49867
49055
|
void client.tableArchived({ table_id: tableId }).then((answered) => {
|
|
@@ -49879,7 +49067,7 @@ function TableNotHere({
|
|
|
49879
49067
|
/* @__PURE__ */ jsx163("p", { className: "text-sm font-medium", children: "This table is archived" }),
|
|
49880
49068
|
/* @__PURE__ */ jsx163("p", { className: "max-w-prose text-xs text-muted-foreground", children: TABLE_IS_ARCHIVED }),
|
|
49881
49069
|
/* @__PURE__ */ jsx163("p", { className: "text-xs text-muted-foreground", children: archivedByLine2(row) }),
|
|
49882
|
-
|
|
49070
|
+
refusal3 ? /* @__PURE__ */ jsx163(RefusalNotice, { error: refusal3 }) : null,
|
|
49883
49071
|
/* @__PURE__ */ jsxs152("div", { className: "flex gap-2", children: [
|
|
49884
49072
|
/* @__PURE__ */ jsx163(
|
|
49885
49073
|
Button110,
|
|
@@ -49996,7 +49184,7 @@ function openingView(activeView, activeDashboardId) {
|
|
|
49996
49184
|
}
|
|
49997
49185
|
function savedViewFromParam(activeView) {
|
|
49998
49186
|
const word = typeof activeView === "string" ? activeView.trim() : "";
|
|
49999
|
-
return
|
|
49187
|
+
return isUuidShape3(word) ? word.toLowerCase() : null;
|
|
50000
49188
|
}
|
|
50001
49189
|
function addressForView(view, layout) {
|
|
50002
49190
|
return view && !view.isDefault ? view.id : layout;
|
|
@@ -50368,7 +49556,7 @@ function TablePage({
|
|
|
50368
49556
|
const [designateRefused, setDesignateRefused] = useState138(null);
|
|
50369
49557
|
const opensAs = view?.isDefault ? view.layout : null;
|
|
50370
49558
|
const canDesignate = Boolean(
|
|
50371
|
-
rights.organise && view && layoutShowing && layoutShowing !== opensAs &&
|
|
49559
|
+
rights.organise && view && layoutShowing && layoutShowing !== opensAs && storeKeepsLayout2(layoutShowing)
|
|
50372
49560
|
);
|
|
50373
49561
|
const layoutShowingLabel = layoutShowing ? LAYOUT_LABEL[layoutShowing] : "";
|
|
50374
49562
|
const designate = async () => {
|
|
@@ -50872,7 +50060,7 @@ function TablePage({
|
|
|
50872
50060
|
QuestionPanel,
|
|
50873
50061
|
{
|
|
50874
50062
|
tableId,
|
|
50875
|
-
activeQuestionId: questionsFromLink && activeItemId &&
|
|
50063
|
+
activeQuestionId: questionsFromLink && activeItemId && isUuidShape3(activeItemId) ? activeItemId : null,
|
|
50876
50064
|
draft: questionDraft
|
|
50877
50065
|
}
|
|
50878
50066
|
) : main === "archived" ? (
|
|
@@ -51128,7 +50316,7 @@ function EntityBoard({ entity, groupBy, cardFields, onOpenRecord, className }) {
|
|
|
51128
50316
|
const writable = !column.readOnly && entity.canUpdate;
|
|
51129
50317
|
const placed = (row) => entityValueText(column, entityCellValue(row, column)) || null;
|
|
51130
50318
|
const lanes = [...words2.map((w) => ({ key: w, label: w })), { key: "", label: `No ${column.label.toLowerCase()}` }];
|
|
51131
|
-
const
|
|
50319
|
+
const rowsOf2 = (key) => entity.rows.filter((r) => (placed(r) ?? "") === key);
|
|
51132
50320
|
const drop = async (event, to) => {
|
|
51133
50321
|
event.preventDefault();
|
|
51134
50322
|
setOver(null);
|
|
@@ -51140,7 +50328,7 @@ function EntityBoard({ entity, groupBy, cardFields, onOpenRecord, className }) {
|
|
|
51140
50328
|
if (says) setRefused({ to, says });
|
|
51141
50329
|
};
|
|
51142
50330
|
return /* @__PURE__ */ jsx164("div", { className: cn98("flex min-h-40 gap-2 overflow-x-auto pb-1", className), "data-records-entity-board": column.key, children: lanes.map((lane) => {
|
|
51143
|
-
const cards =
|
|
50331
|
+
const cards = rowsOf2(lane.key);
|
|
51144
50332
|
if (lane.key === "" && cards.length === 0) return null;
|
|
51145
50333
|
return /* @__PURE__ */ jsxs153(
|
|
51146
50334
|
"section",
|
|
@@ -51182,9 +50370,9 @@ function EntityBoard({ entity, groupBy, cardFields, onOpenRecord, className }) {
|
|
|
51182
50370
|
);
|
|
51183
50371
|
}) });
|
|
51184
50372
|
}
|
|
51185
|
-
function blockOfAnswer(answer,
|
|
50373
|
+
function blockOfAnswer(answer, base2, by) {
|
|
51186
50374
|
if (!answer.ok) {
|
|
51187
|
-
return { ...
|
|
50375
|
+
return { ...base2, refused: refusalSentence(answer.error) || "This chart could not be read.", ...answer.error.code ? { sqlstate: answer.error.code } : {} };
|
|
51188
50376
|
}
|
|
51189
50377
|
const rows = answer.data.rows.filter((r) => by ? r.kind !== "total" : r.kind === "total").map((r) => {
|
|
51190
50378
|
const groups = {};
|
|
@@ -51196,7 +50384,7 @@ function blockOfAnswer(answer, base, by) {
|
|
|
51196
50384
|
for (const [k, v] of Object.entries(r.measures ?? {})) measuresOut[k] = typeof v === "number" ? v : v === null ? null : Number(v);
|
|
51197
50385
|
return { groups, measures: measuresOut, row_count: Number(r.row_count) };
|
|
51198
50386
|
});
|
|
51199
|
-
return { ...
|
|
50387
|
+
return { ...base2, rows };
|
|
51200
50388
|
}
|
|
51201
50389
|
function EntityChartBlock({ source, kind, by, measure, title, where, organization, centerValue, variant, className }) {
|
|
51202
50390
|
const client = useRecordsClient99();
|
|
@@ -51204,9 +50392,9 @@ function EntityChartBlock({ source, kind, by, measure, title, where, organizatio
|
|
|
51204
50392
|
const ask = JSON.stringify([source.token, by ?? null, m, where ?? null, organization ?? null]);
|
|
51205
50393
|
const question = entityChartQuestion({ by, measure, where, organization });
|
|
51206
50394
|
const measures = [m.op === "count" ? { op: "count" } : { op: m.op, key: m.of }];
|
|
51207
|
-
const
|
|
50395
|
+
const base2 = { title: title ?? "", kind, measures, group_by: by ? [by] : [] };
|
|
51208
50396
|
const seeded = useSeededAnswerAt(`entity-chart:${ask}`, (c) => c.drillAsk({ source, question }));
|
|
51209
|
-
const [block, setBlock] = useState139(() => seeded ? blockOfAnswer({ ok: true, data: seeded.data },
|
|
50397
|
+
const [block, setBlock] = useState139(() => seeded ? blockOfAnswer({ ok: true, data: seeded.data }, base2, by) : null);
|
|
51210
50398
|
const seededFor = useRef63(seeded ? { ask: `${ask}|${kind}|${title ?? ""}`, at: seeded.at } : null);
|
|
51211
50399
|
useEffect118(() => {
|
|
51212
50400
|
const held = seededFor.current;
|
|
@@ -51215,7 +50403,7 @@ function EntityChartBlock({ source, kind, by, measure, title, where, organizatio
|
|
|
51215
50403
|
let cancelled = false;
|
|
51216
50404
|
void client.drillAsk({ source, question }).then((answer) => {
|
|
51217
50405
|
if (cancelled) return;
|
|
51218
|
-
setBlock(blockOfAnswer(answer,
|
|
50406
|
+
setBlock(blockOfAnswer(answer, base2, by));
|
|
51219
50407
|
});
|
|
51220
50408
|
return () => {
|
|
51221
50409
|
cancelled = true;
|
|
@@ -51493,7 +50681,7 @@ function BindingDetails({
|
|
|
51493
50681
|
}, [disabled, shape, binding, fields.loading, fieldList, table.data, onChange]);
|
|
51494
50682
|
const selectShape = (next) => {
|
|
51495
50683
|
if (next === shape) return;
|
|
51496
|
-
const
|
|
50684
|
+
const base2 = {
|
|
51497
50685
|
kind: "merge_field",
|
|
51498
50686
|
source: "record",
|
|
51499
50687
|
semantic_type: next,
|
|
@@ -51501,21 +50689,21 @@ function BindingDetails({
|
|
|
51501
50689
|
missing: binding.missing,
|
|
51502
50690
|
override_policy: "shown_locked"
|
|
51503
50691
|
};
|
|
51504
|
-
if (next !== "collection" && binding.record_id)
|
|
51505
|
-
if (next === "value" && binding.field_key)
|
|
50692
|
+
if (next !== "collection" && binding.record_id) base2.record_id = binding.record_id;
|
|
50693
|
+
if (next === "value" && binding.field_key) base2.field_key = binding.field_key;
|
|
51506
50694
|
if (next === "collection") {
|
|
51507
50695
|
const limit = binding.limit ?? defaultRowLimit;
|
|
51508
|
-
if (limit)
|
|
50696
|
+
if (limit) base2.limit = limit;
|
|
51509
50697
|
}
|
|
51510
50698
|
if (next !== "value" && binding.transform) {
|
|
51511
|
-
|
|
50699
|
+
base2.transform = {
|
|
51512
50700
|
name: "list",
|
|
51513
50701
|
template: binding.transform.template,
|
|
51514
50702
|
...binding.transform.join !== void 0 ? { join: binding.transform.join } : {},
|
|
51515
|
-
...next === "collection" &&
|
|
50703
|
+
...next === "collection" && base2.limit !== void 0 ? { max: base2.limit } : {}
|
|
51516
50704
|
};
|
|
51517
50705
|
}
|
|
51518
|
-
onChange(
|
|
50706
|
+
onChange(base2);
|
|
51519
50707
|
};
|
|
51520
50708
|
const fieldOptions = fieldList.map((f) => ({ value: f.key, label: fieldName(f) }));
|
|
51521
50709
|
const template = binding.transform?.template ?? "";
|
|
@@ -51829,10 +51017,21 @@ function PreviewForms({ preview, booking }) {
|
|
|
51829
51017
|
] }, p.id)) : null
|
|
51830
51018
|
] });
|
|
51831
51019
|
}
|
|
51020
|
+
var export_QUESTION_OPS = question_exports.QUESTION_OPS;
|
|
51021
|
+
var export_QUESTION_SURFACE = question_exports.QUESTION_SURFACE;
|
|
51832
51022
|
var export_asRefusal = refusals_exports.asRefusal;
|
|
51023
|
+
var export_askQuestion = question_exports.askQuestion;
|
|
51024
|
+
var export_flatWhere = question_exports.flatWhere;
|
|
51025
|
+
var export_measurableFields = question_exports.measurableFields;
|
|
51026
|
+
var export_newQuestion = question_exports.newQuestion;
|
|
51027
|
+
var export_questionArchive = question_exports.questionArchive;
|
|
51028
|
+
var export_questionFromDefinition = question_exports.questionFromDefinition;
|
|
51029
|
+
var export_questionSave = question_exports.questionSave;
|
|
51030
|
+
var export_questionsOf = question_exports.questionsOf;
|
|
51833
51031
|
var export_refusal = refusals_exports.refusal;
|
|
51834
51032
|
var export_refusalFromThrown = refusals_exports.refusalFromThrown;
|
|
51835
51033
|
var export_refusalOr = refusals_exports.refusalOr;
|
|
51034
|
+
var export_unreadableKeys = question_exports.unreadableKeys;
|
|
51836
51035
|
export {
|
|
51837
51036
|
ABSENCE_WORD_LABEL,
|
|
51838
51037
|
ABSENCE_WORD_VALUES,
|
|
@@ -52006,8 +51205,8 @@ export {
|
|
|
52006
51205
|
ProvenanceBadge,
|
|
52007
51206
|
PublicPicturePicker,
|
|
52008
51207
|
PublicViewPage,
|
|
52009
|
-
QUESTION_OPS,
|
|
52010
|
-
QUESTION_SURFACE,
|
|
51208
|
+
export_QUESTION_OPS as QUESTION_OPS,
|
|
51209
|
+
export_QUESTION_SURFACE as QUESTION_SURFACE,
|
|
52011
51210
|
QuestionAnswerView,
|
|
52012
51211
|
QuestionPanel,
|
|
52013
51212
|
RECORDS_GRID_ROW_PX,
|
|
@@ -52045,8 +51244,8 @@ export {
|
|
|
52045
51244
|
STANDARD_VERBS,
|
|
52046
51245
|
STORE_ANSWERS_THESE,
|
|
52047
51246
|
STORE_DECIDES_REASON,
|
|
52048
|
-
STORE_KEEPS_TIMELINE,
|
|
52049
|
-
STORE_KEPT_LAYOUTS,
|
|
51247
|
+
STORE_KEEPS_TIMELINE2 as STORE_KEEPS_TIMELINE,
|
|
51248
|
+
STORE_KEPT_LAYOUTS2 as STORE_KEPT_LAYOUTS,
|
|
52050
51249
|
STRIP_FEATURE_ROWS,
|
|
52051
51250
|
SUBSCRIPTION_CADENCES,
|
|
52052
51251
|
SUBSCRIPTION_CADENCE_LABEL,
|
|
@@ -52120,7 +51319,7 @@ export {
|
|
|
52120
51319
|
archivedRowLine,
|
|
52121
51320
|
export_asRefusal as asRefusal,
|
|
52122
51321
|
askExampleFor,
|
|
52123
|
-
askQuestion,
|
|
51322
|
+
export_askQuestion as askQuestion,
|
|
52124
51323
|
askableFields,
|
|
52125
51324
|
bindingPlaceholdersFor,
|
|
52126
51325
|
blockFromSpec,
|
|
@@ -52204,7 +51403,7 @@ export {
|
|
|
52204
51403
|
fieldTypeLabel,
|
|
52205
51404
|
fieldsForNewColumns,
|
|
52206
51405
|
filterTargets,
|
|
52207
|
-
flatWhere,
|
|
51406
|
+
export_flatWhere as flatWhere,
|
|
52208
51407
|
footerOf,
|
|
52209
51408
|
formDeclareArgs2 as formDeclareArgs,
|
|
52210
51409
|
formEmbedSnippet2 as formEmbedSnippet,
|
|
@@ -52263,10 +51462,10 @@ export {
|
|
|
52263
51462
|
looksLikeId,
|
|
52264
51463
|
machineIdentityIn,
|
|
52265
51464
|
mayNotRestoreLine,
|
|
52266
|
-
measurableFields,
|
|
51465
|
+
export_measurableFields as measurableFields,
|
|
52267
51466
|
memberName,
|
|
52268
51467
|
moveRecordValue,
|
|
52269
|
-
newQuestion,
|
|
51468
|
+
export_newQuestion as newQuestion,
|
|
52270
51469
|
nextInWords,
|
|
52271
51470
|
nextSummaryAt,
|
|
52272
51471
|
notAChoiceSentence,
|
|
@@ -52292,11 +51491,11 @@ export {
|
|
|
52292
51491
|
previewLine,
|
|
52293
51492
|
previewWords,
|
|
52294
51493
|
publiclyAnswerable,
|
|
52295
|
-
questionArchive,
|
|
52296
|
-
questionFromDefinition,
|
|
51494
|
+
export_questionArchive as questionArchive,
|
|
51495
|
+
export_questionFromDefinition as questionFromDefinition,
|
|
52297
51496
|
questionFromWords,
|
|
52298
|
-
questionSave,
|
|
52299
|
-
questionsOf,
|
|
51497
|
+
export_questionSave as questionSave,
|
|
51498
|
+
export_questionsOf as questionsOf,
|
|
52300
51499
|
railFromParam,
|
|
52301
51500
|
readLooks,
|
|
52302
51501
|
readTableShape,
|
|
@@ -52347,7 +51546,7 @@ export {
|
|
|
52347
51546
|
starterPageBlocks,
|
|
52348
51547
|
stepFromAgent,
|
|
52349
51548
|
storeDecidesRights,
|
|
52350
|
-
storeKeepsLayout,
|
|
51549
|
+
storeKeepsLayout2 as storeKeepsLayout,
|
|
52351
51550
|
storePublishesKind,
|
|
52352
51551
|
styleFromDecorations,
|
|
52353
51552
|
submissionStamp2 as submissionStamp,
|
|
@@ -52366,7 +51565,7 @@ export {
|
|
|
52366
51565
|
tokenFor,
|
|
52367
51566
|
unknownRailLine,
|
|
52368
51567
|
unknownViewLine,
|
|
52369
|
-
unreadableKeys,
|
|
51568
|
+
export_unreadableKeys as unreadableKeys,
|
|
52370
51569
|
useAddressDrill,
|
|
52371
51570
|
useCanShare,
|
|
52372
51571
|
useChoiceNudge,
|