@ai-matrx/records-ui 0.113.31 → 0.113.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -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 +445 -1295
- 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 +360 -1159
- 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,8 @@ 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";
|
|
952
954
|
function sortRefusal(f) {
|
|
953
955
|
if (!computedOnRead(f)) return null;
|
|
954
956
|
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,23 +963,6 @@ function computedOnRead(f) {
|
|
|
961
963
|
const kind = String(editorKindFor(f));
|
|
962
964
|
return (f.type === "formula" || kind === "formula" || kind === "lookup" || kind === "rollup") && String(f.compute_on ?? "read") === "read";
|
|
963
965
|
}
|
|
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
966
|
function containsPattern(text) {
|
|
982
967
|
return `(?i)${text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`;
|
|
983
968
|
}
|
|
@@ -1076,12 +1061,12 @@ function dayWindow(day, holdsDays) {
|
|
|
1076
1061
|
const ymd = (t) => `${t.getUTCFullYear()}-${String(t.getUTCMonth() + 1).padStart(2, "0")}-${String(t.getUTCDate()).padStart(2, "0")}`;
|
|
1077
1062
|
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
1063
|
}
|
|
1079
|
-
function storeQuestion(fields,
|
|
1064
|
+
function storeQuestion(fields, base2, columnFilters, now = /* @__PURE__ */ new Date()) {
|
|
1080
1065
|
const refused = [];
|
|
1081
1066
|
const flat = {};
|
|
1082
1067
|
const rules = [];
|
|
1083
|
-
if (
|
|
1084
|
-
else if (
|
|
1068
|
+
if (base2 && isRuleFilter(base2)) rules.push(base2);
|
|
1069
|
+
else if (base2) Object.assign(flat, base2);
|
|
1085
1070
|
for (const [key, value] of Object.entries(columnFilters)) {
|
|
1086
1071
|
if (!value) continue;
|
|
1087
1072
|
const f = fields.find((candidate) => candidate.key === key);
|
|
@@ -1622,32 +1607,7 @@ function useLabelWait(field2) {
|
|
|
1622
1607
|
}
|
|
1623
1608
|
|
|
1624
1609
|
// 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
|
-
}
|
|
1610
|
+
import { defaultSortOf } from "@ai-matrx/records/first-page";
|
|
1651
1611
|
var ROW_HEIGHT_PX = {
|
|
1652
1612
|
compact: 28,
|
|
1653
1613
|
normal: void 0,
|
|
@@ -2005,7 +1965,7 @@ function FieldRetype({ field: field2, tableId, onRetyped }) {
|
|
|
2005
1965
|
const [to, setTo] = useState4(null);
|
|
2006
1966
|
const [preview, setPreview] = useState4(null);
|
|
2007
1967
|
const [asking, setAsking] = useState4(false);
|
|
2008
|
-
const [
|
|
1968
|
+
const [refusal3, setRefusal] = useState4(null);
|
|
2009
1969
|
const [busy, setBusy] = useState4(false);
|
|
2010
1970
|
const [said2, setSaid] = useState4(null);
|
|
2011
1971
|
const name = fieldName(field2);
|
|
@@ -2103,7 +2063,7 @@ function FieldRetype({ field: field2, tableId, onRetyped }) {
|
|
|
2103
2063
|
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
2064
|
preview.partial ? ". Counted over the first 1,000 different values." : "."
|
|
2105
2065
|
] }) : null,
|
|
2106
|
-
|
|
2066
|
+
refusal3 ? /* @__PURE__ */ jsx6(RefusalNotice, { error: refusal3 }) : null,
|
|
2107
2067
|
said2 ? /* @__PURE__ */ jsx6("p", { role: "status", className: "text-[11px] text-muted-foreground", "data-records-retype-done": "", children: said2 }) : null
|
|
2108
2068
|
] });
|
|
2109
2069
|
}
|
|
@@ -2879,10 +2839,10 @@ function TableDetails({
|
|
|
2879
2839
|
if (slots.details.current === slot) slots.details.current = null;
|
|
2880
2840
|
};
|
|
2881
2841
|
}, [slots]);
|
|
2882
|
-
const write = async (patch,
|
|
2842
|
+
const write = async (patch, base2) => {
|
|
2883
2843
|
setBusy(true);
|
|
2884
2844
|
setRefused(null);
|
|
2885
|
-
const written = await (0, writeOnTheWinningVersion_exports.updateOnTheWinningVersion)(client, tableId, patch, await (0, recordVersions_exports.readTableVersionNow)(client, tableId),
|
|
2845
|
+
const written = await (0, writeOnTheWinningVersion_exports.updateOnTheWinningVersion)(client, tableId, patch, await (0, recordVersions_exports.readTableVersionNow)(client, tableId), base2);
|
|
2886
2846
|
setBusy(false);
|
|
2887
2847
|
if (!written.ok) {
|
|
2888
2848
|
setRefused(refusalSentence(written.error));
|
|
@@ -3981,13 +3941,13 @@ function styleFromDecorations(decorations, fields) {
|
|
|
3981
3941
|
return style;
|
|
3982
3942
|
}
|
|
3983
3943
|
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 ??
|
|
3944
|
+
const base2 = styleFromDecorations(decorations, fields);
|
|
3945
|
+
if (!viewStyle) return base2;
|
|
3946
|
+
const colorBy = viewStyle.colorBy ?? base2.colorBy;
|
|
3947
|
+
const rules = viewStyle.rules ?? base2.rules;
|
|
3948
|
+
const rows = viewStyle.rows ?? base2.rows;
|
|
3949
|
+
const columns = viewStyle.columns ?? base2.columns;
|
|
3950
|
+
const cells = viewStyle.cells ?? base2.cells;
|
|
3991
3951
|
return {
|
|
3992
3952
|
version: 1,
|
|
3993
3953
|
...colorBy !== void 0 ? { colorBy } : {},
|
|
@@ -4406,7 +4366,7 @@ function RelationPicker({ field: field2, value, onChange, disabled, id, classNam
|
|
|
4406
4366
|
const client = useOptionalRecordsClient3();
|
|
4407
4367
|
const [rows, setRows] = useState12(null);
|
|
4408
4368
|
const [words2, setWords] = useState12({});
|
|
4409
|
-
const [
|
|
4369
|
+
const [refusal3, setRefusal] = useState12(null);
|
|
4410
4370
|
const [search, setSearch] = useState12("");
|
|
4411
4371
|
const [open, setOpenState] = useState12(autoOpen === true);
|
|
4412
4372
|
const onCloseRef = useRef7(onClose);
|
|
@@ -4590,8 +4550,8 @@ function RelationPicker({ field: field2, value, onChange, disabled, id, classNam
|
|
|
4590
4550
|
})),
|
|
4591
4551
|
onPick: toggle,
|
|
4592
4552
|
notice: /* @__PURE__ */ jsxs13(Fragment4, { children: [
|
|
4593
|
-
|
|
4594
|
-
!rows && !
|
|
4553
|
+
refusal3 ? /* @__PURE__ */ jsx15(RefusalLine, { error: refusal3, className: "p-2" }) : null,
|
|
4554
|
+
!rows && !refusal3 ? /* @__PURE__ */ jsx15("p", { className: "p-2 text-xs text-muted-foreground", children: "Reading\u2026" }) : null,
|
|
4595
4555
|
full ? /* @__PURE__ */ jsxs13("p", { className: "p-2 text-xs text-muted-foreground", children: [
|
|
4596
4556
|
fieldName(field2),
|
|
4597
4557
|
" can point at ",
|
|
@@ -5029,500 +4989,35 @@ import { Badge as Badge5, cn as cn19 } from "@ai-matrx/design-system";
|
|
|
5029
4989
|
import { createContext as createContext4, useContext as useContext4 } from "react";
|
|
5030
4990
|
|
|
5031
4991
|
// 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;
|
|
4992
|
+
import { bindFirstPageCodec } from "@ai-matrx/records/first-page";
|
|
5049
4993
|
|
|
5050
4994
|
// 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"
|
|
4995
|
+
import * as base from "@ai-matrx/records/views";
|
|
4996
|
+
import {
|
|
4997
|
+
STORE_KEEPS_TIMELINE,
|
|
4998
|
+
STORE_KEPT_LAYOUTS,
|
|
4999
|
+
VIEW_KEYS,
|
|
5000
|
+
storeKeepsLayout,
|
|
5001
|
+
viewKeysFor,
|
|
5002
|
+
viewSettingsFor
|
|
5003
|
+
} from "@ai-matrx/records/views";
|
|
5004
|
+
var gridPresentationCodec = {
|
|
5005
|
+
parse: parseGridPresentation,
|
|
5006
|
+
isEmpty: presentationIsEmpty,
|
|
5007
|
+
toDocument: (presentation) => JSON.parse(presentationDocument(presentation))
|
|
5507
5008
|
};
|
|
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
|
-
}
|
|
5009
|
+
var boundViews = base.bindViewCodec(gridPresentationCodec);
|
|
5010
|
+
var { viewSettings, viewSettingsPatch } = boundViews;
|
|
5523
5011
|
|
|
5524
5012
|
// src/firstPage.ts
|
|
5525
|
-
|
|
5013
|
+
import {
|
|
5014
|
+
EMBEDDED_PAGE_SIZE,
|
|
5015
|
+
TABLE_PAGE_SIZE,
|
|
5016
|
+
firstGridPageArgs,
|
|
5017
|
+
serverRowsOf,
|
|
5018
|
+
viewFilterOf
|
|
5019
|
+
} from "@ai-matrx/records/first-page";
|
|
5020
|
+
var { firstGridPageRequest, askTablePageSeed } = bindFirstPageCodec(gridPresentationCodec);
|
|
5526
5021
|
|
|
5527
5022
|
// src/embeddedLook.tsx
|
|
5528
5023
|
var EMBEDDED_LOOK = { blankEmpty: true, choiceDot: true, plainRelation: true };
|
|
@@ -6777,7 +6272,7 @@ function RetiredValues({
|
|
|
6777
6272
|
}) {
|
|
6778
6273
|
const client = useRecordsClient7();
|
|
6779
6274
|
const [busy, setBusy] = useState20(null);
|
|
6780
|
-
const [
|
|
6275
|
+
const [refusal3, setRefusal] = useState20(null);
|
|
6781
6276
|
const [said2, setSaid] = useState20(null);
|
|
6782
6277
|
const [missing, setMissing] = useState20(null);
|
|
6783
6278
|
const kept = retiredValuesOf(document2);
|
|
@@ -6826,7 +6321,7 @@ function RetiredValues({
|
|
|
6826
6321
|
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
6322
|
] }),
|
|
6828
6323
|
entry.reason ? /* @__PURE__ */ jsx26("p", { className: "text-[11px] text-muted-foreground", children: entry.reason }) : null,
|
|
6829
|
-
|
|
6324
|
+
refusal3?.key === id ? /* @__PURE__ */ jsx26(RefusalNotice, { error: refusal3.error }) : null,
|
|
6830
6325
|
missing === id ? /* @__PURE__ */ jsxs23("p", { className: "text-[11px] text-muted-foreground", children: [
|
|
6831
6326
|
"No earlier version of ",
|
|
6832
6327
|
name,
|
|
@@ -7681,7 +7176,7 @@ function ruleWords(rules) {
|
|
|
7681
7176
|
function rulesChanged(was, now) {
|
|
7682
7177
|
return ruleWords(was) !== ruleWords(now);
|
|
7683
7178
|
}
|
|
7684
|
-
function
|
|
7179
|
+
function holdsNumbers3(field2) {
|
|
7685
7180
|
return field2.type === "range";
|
|
7686
7181
|
}
|
|
7687
7182
|
function groupValue(value, numbers) {
|
|
@@ -7692,7 +7187,7 @@ function groupValue(value, numbers) {
|
|
|
7692
7187
|
function FieldRulePreview({ field: field2, tableId, rules }) {
|
|
7693
7188
|
const client = useRecordsClient9();
|
|
7694
7189
|
const [preview, setPreview] = useState23(null);
|
|
7695
|
-
const [
|
|
7190
|
+
const [refusal3, setRefusal] = useState23(null);
|
|
7696
7191
|
const key = useMemo11(() => ruleWords(rules), [rules]);
|
|
7697
7192
|
const latest = useRef13(rules);
|
|
7698
7193
|
latest.current = rules;
|
|
@@ -7708,7 +7203,7 @@ function FieldRulePreview({ field: field2, tableId, rules }) {
|
|
|
7708
7203
|
setRefusal(answer.error);
|
|
7709
7204
|
return;
|
|
7710
7205
|
}
|
|
7711
|
-
const numbers =
|
|
7206
|
+
const numbers = holdsNumbers3(field2);
|
|
7712
7207
|
const groups = answer.data.map((row) => ({ value: groupValue(row.groups[field2.key] ?? null, numbers), count: row.row_count }));
|
|
7713
7208
|
setPreview(previewRuleChange(latest.current, groups, answer.data.length >= PREVIEW_GROUPS2));
|
|
7714
7209
|
});
|
|
@@ -7718,7 +7213,7 @@ function FieldRulePreview({ field: field2, tableId, rules }) {
|
|
|
7718
7213
|
clearTimeout(timer);
|
|
7719
7214
|
};
|
|
7720
7215
|
}, [client, tableId, field2.key, key]);
|
|
7721
|
-
if (
|
|
7216
|
+
if (refusal3) return /* @__PURE__ */ jsx31(RefusalNotice, { error: refusal3 });
|
|
7722
7217
|
if (!preview) {
|
|
7723
7218
|
return /* @__PURE__ */ jsxs27("p", { className: "text-[11px] text-muted-foreground", "data-records-rule-preview": "counting", children: [
|
|
7724
7219
|
"Counting ",
|
|
@@ -7779,9 +7274,9 @@ function choiceDisplayPatch(field2, rows) {
|
|
|
7779
7274
|
}
|
|
7780
7275
|
function lookFollowsRenames(field2, look, renames) {
|
|
7781
7276
|
if (renames.size === 0) return look;
|
|
7782
|
-
const
|
|
7783
|
-
const choices =
|
|
7784
|
-
if (!
|
|
7277
|
+
const base2 = look ?? displayFormatOf(field2);
|
|
7278
|
+
const choices = base2 && Array.isArray(base2.options["choices"]) ? base2.options["choices"] : null;
|
|
7279
|
+
if (!base2 || !choices) return look;
|
|
7785
7280
|
let moved = false;
|
|
7786
7281
|
const next = choices.map((c) => {
|
|
7787
7282
|
const was = typeof c["value"] === "string" ? c["value"] : null;
|
|
@@ -7791,11 +7286,11 @@ function lookFollowsRenames(field2, look, renames) {
|
|
|
7791
7286
|
return { ...c, value: now };
|
|
7792
7287
|
});
|
|
7793
7288
|
if (!moved) return look;
|
|
7794
|
-
return { id:
|
|
7289
|
+
return { id: base2.id, options: { ...base2.options, choices: next } };
|
|
7795
7290
|
}
|
|
7796
7291
|
function choiceLookFromList(field2, start, rows) {
|
|
7797
|
-
const
|
|
7798
|
-
const colorRows =
|
|
7292
|
+
const base2 = startingChoiceColors(field2, start.map((r) => r.words.trim()).filter((w) => w !== ""));
|
|
7293
|
+
const colorRows = base2.map((row) => {
|
|
7799
7294
|
const was = start.find((r) => choiceWord(r.words) === choiceWord(row.value));
|
|
7800
7295
|
const now = was?.id ? rows.find((r) => r.id === was.id) : void 0;
|
|
7801
7296
|
return now ? { value: row.value, color: now.color ?? null } : row;
|
|
@@ -8248,9 +7743,9 @@ function storageOf(field2) {
|
|
|
8248
7743
|
}
|
|
8249
7744
|
}
|
|
8250
7745
|
function formatMenu(field2) {
|
|
8251
|
-
const
|
|
8252
|
-
if (
|
|
8253
|
-
if (
|
|
7746
|
+
const base2 = storageOf(field2);
|
|
7747
|
+
if (base2 === null) return { groups: [], otherKinds: [] };
|
|
7748
|
+
if (base2 === "formula") {
|
|
8254
7749
|
const groups2 = [];
|
|
8255
7750
|
for (const def of FIELD_FORMAT_LIST) {
|
|
8256
7751
|
if (neverALook(def) || KIND_WORD[def.id] || def.id === "boolean") continue;
|
|
@@ -8260,7 +7755,7 @@ function formatMenu(field2) {
|
|
|
8260
7755
|
}
|
|
8261
7756
|
return { groups: groups2, otherKinds: [] };
|
|
8262
7757
|
}
|
|
8263
|
-
const groups = groupedFormatsForBase(
|
|
7758
|
+
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
7759
|
const own3 = new Set(groups.flatMap((g) => g.formats.map((d) => d.id)));
|
|
8265
7760
|
const otherKinds = [];
|
|
8266
7761
|
for (const def of FIELD_FORMAT_LIST) {
|
|
@@ -10832,7 +10327,7 @@ function FieldControl({ field: field2, value, onChange, disabled, id, autoOpen,
|
|
|
10832
10327
|
}
|
|
10833
10328
|
function TypedWordsControl({ field: field2, value, onChange, disabled, id }) {
|
|
10834
10329
|
const [text, setText] = useState32(() => openingText(field2, value));
|
|
10835
|
-
const [
|
|
10330
|
+
const [refusal3, setRefusal] = useState32(null);
|
|
10836
10331
|
const [why, setWhy] = useState32(void 0);
|
|
10837
10332
|
const sent = useRef18(value);
|
|
10838
10333
|
useEffect22(() => {
|
|
@@ -10863,11 +10358,11 @@ function TypedWordsControl({ field: field2, value, onChange, disabled, id }) {
|
|
|
10863
10358
|
value: text,
|
|
10864
10359
|
disabled,
|
|
10865
10360
|
autoComplete: "off",
|
|
10866
|
-
"aria-invalid":
|
|
10361
|
+
"aria-invalid": refusal3 ? true : void 0,
|
|
10867
10362
|
placeholder: helper ? typedDatePlaceholder(helper) : void 0,
|
|
10868
10363
|
onChange: (e) => retype(e.target.value),
|
|
10869
10364
|
onBlur: () => {
|
|
10870
|
-
if (!
|
|
10365
|
+
if (!refusal3) return;
|
|
10871
10366
|
setText(openingText(field2, sent.current));
|
|
10872
10367
|
setRefusal(null);
|
|
10873
10368
|
}
|
|
@@ -10875,7 +10370,7 @@ function TypedWordsControl({ field: field2, value, onChange, disabled, id }) {
|
|
|
10875
10370
|
),
|
|
10876
10371
|
helper && !disabled ? /* @__PURE__ */ jsx42(TypedDateHelper, { kind: helper, text, onText: retype, label: fieldName(field2) }) : null
|
|
10877
10372
|
] }),
|
|
10878
|
-
|
|
10373
|
+
refusal3 ? /* @__PURE__ */ jsx42(FloatingRefusal, { text: refusal3, why }) : null
|
|
10879
10374
|
] });
|
|
10880
10375
|
}
|
|
10881
10376
|
function typedDatePlaceholder(helper) {
|
|
@@ -10979,7 +10474,7 @@ function inTheStoresOrder(options) {
|
|
|
10979
10474
|
function OptionControl({ field: field2, value, onChange, disabled, id, autoOpen, onClose, onCancel, addsChoices, initialSearch, asForm, onChosen }) {
|
|
10980
10475
|
const client = useOptionalRecordsClient10();
|
|
10981
10476
|
const [options, setOptions] = useState32(null);
|
|
10982
|
-
const [
|
|
10477
|
+
const [refusal3, setRefusal] = useState32(null);
|
|
10983
10478
|
const [reread, setReread] = useState32(0);
|
|
10984
10479
|
useEffect22(() => {
|
|
10985
10480
|
if (!client) return;
|
|
@@ -11011,8 +10506,8 @@ function OptionControl({ field: field2, value, onChange, disabled, id, autoOpen,
|
|
|
11011
10506
|
/* @__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
10507
|
] });
|
|
11013
10508
|
}
|
|
11014
|
-
if (
|
|
11015
|
-
return /* @__PURE__ */ jsx42("div", { id, children: /* @__PURE__ */ jsx42(RefusalLine, { error:
|
|
10509
|
+
if (refusal3)
|
|
10510
|
+
return /* @__PURE__ */ jsx42("div", { id, children: /* @__PURE__ */ jsx42(RefusalLine, { error: refusal3 }) });
|
|
11016
10511
|
if (!options) return /* @__PURE__ */ jsx42("p", { id, className: "text-xs text-muted-foreground", children: "Reading this field's choices\u2026" });
|
|
11017
10512
|
if (asForm && options.length > 0) {
|
|
11018
10513
|
const titled = (option) => recordName(option.data, null, "Unnamed choice");
|
|
@@ -11751,7 +11246,7 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
11751
11246
|
startedFrom.current = null;
|
|
11752
11247
|
}, []);
|
|
11753
11248
|
const writeCellNow = useCallback10(
|
|
11754
|
-
async (rowId, key, value,
|
|
11249
|
+
async (rowId, key, value, base2, resent = false) => {
|
|
11755
11250
|
const id = cellKey(rowId, key);
|
|
11756
11251
|
const adding = isChoiceAddition(value) ? value : null;
|
|
11757
11252
|
const shown4 = adding ? adding.value : value;
|
|
@@ -11768,7 +11263,7 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
11768
11263
|
let version = await versionOf(source, versions.current, versionReads.current, rowId);
|
|
11769
11264
|
const drawnNow = await source.seen(rowId);
|
|
11770
11265
|
const storedNow = rowsNow.current.find((r) => r.id === rowId)?.document?.[key];
|
|
11771
|
-
if (drawnNow !== null && (version === null || drawnNow > version) && sameValue(storedNow,
|
|
11266
|
+
if (drawnNow !== null && (version === null || drawnNow > version) && sameValue(storedNow, base2)) {
|
|
11772
11267
|
version = drawnNow;
|
|
11773
11268
|
rememberVersion(versions.current, rowId, drawnNow);
|
|
11774
11269
|
}
|
|
@@ -11797,13 +11292,13 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
11797
11292
|
if (written.ok) {
|
|
11798
11293
|
rememberVersion(versions.current, rowId, written.data);
|
|
11799
11294
|
source.wrote(rowId, written.data);
|
|
11800
|
-
settling.current.set(id,
|
|
11801
|
-
writtenRef.current?.({ rowId, key, before:
|
|
11295
|
+
settling.current.set(id, base2);
|
|
11296
|
+
writtenRef.current?.({ rowId, key, before: base2, after: shown4, version: written.data });
|
|
11802
11297
|
afterWrite();
|
|
11803
11298
|
return;
|
|
11804
11299
|
}
|
|
11805
11300
|
if (isUnsentWrite(written.error)) {
|
|
11806
|
-
setRefusals((held) => ({ ...held, [id]: { error: written.error, conflict: null, attempted: value, unsent: true, base } }));
|
|
11301
|
+
setRefusals((held) => ({ ...held, [id]: { error: written.error, conflict: null, attempted: value, unsent: true, base: base2 } }));
|
|
11807
11302
|
return;
|
|
11808
11303
|
}
|
|
11809
11304
|
setOptimistic((held) => {
|
|
@@ -11815,8 +11310,8 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
11815
11310
|
if (written.error.code === "stale_write") {
|
|
11816
11311
|
if (conflict) rememberVersion(versions.current, rowId, conflict.current_version);
|
|
11817
11312
|
else versions.current.delete(rowId);
|
|
11818
|
-
if (conflict && !resent && sameValue(conflict.contested_fields[key],
|
|
11819
|
-
await writeCellNow(rowId, key, value,
|
|
11313
|
+
if (conflict && !resent && sameValue(conflict.contested_fields[key], base2)) {
|
|
11314
|
+
await writeCellNow(rowId, key, value, base2, true);
|
|
11820
11315
|
return;
|
|
11821
11316
|
}
|
|
11822
11317
|
}
|
|
@@ -11833,9 +11328,9 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
11833
11328
|
[client, reload, afterWrite, source]
|
|
11834
11329
|
);
|
|
11835
11330
|
const writeCell = useCallback10(
|
|
11836
|
-
(rowId, key, value,
|
|
11331
|
+
(rowId, key, value, base2) => {
|
|
11837
11332
|
const behind = queues.current.get(rowId) ?? Promise.resolve();
|
|
11838
|
-
const next = behind.then(() => writeCellNow(rowId, key, value,
|
|
11333
|
+
const next = behind.then(() => writeCellNow(rowId, key, value, base2));
|
|
11839
11334
|
queues.current.set(
|
|
11840
11335
|
rowId,
|
|
11841
11336
|
next.then(
|
|
@@ -12188,7 +11683,7 @@ function GridCell({
|
|
|
12188
11683
|
};
|
|
12189
11684
|
const value = editing ? editing.valueFor(row, field2) : row.document?.[field2.key];
|
|
12190
11685
|
const state = editing ? editing.stateOf(row.id, field2.key) : null;
|
|
12191
|
-
const
|
|
11686
|
+
const refusal3 = editing ? editing.refusalOf(row.id, field2.key) : null;
|
|
12192
11687
|
const editable = Boolean(editing) && canWrite && fieldIsEditable(field2);
|
|
12193
11688
|
if (open && editing) {
|
|
12194
11689
|
return /* @__PURE__ */ jsxs39("span", { "data-records-open-cell": "", className: "relative block w-full min-w-0", children: [
|
|
@@ -12225,10 +11720,10 @@ function GridCell({
|
|
|
12225
11720
|
// state they are in, so only Discard is offered. It is INSIDE the open
|
|
12226
11721
|
// cell, so pressing Discard is not "focus left the cell" — which would
|
|
12227
11722
|
// commit the refused value one more time on its way out.
|
|
12228
|
-
|
|
11723
|
+
refusal3 && !refusal3.conflict ? /* @__PURE__ */ jsx44(
|
|
12229
11724
|
RefusalNotice,
|
|
12230
11725
|
{
|
|
12231
|
-
error:
|
|
11726
|
+
error: refusal3.error,
|
|
12232
11727
|
className: "py-1.5 text-left",
|
|
12233
11728
|
onDiscard: () => editing.discard(row.id, field2.key)
|
|
12234
11729
|
}
|
|
@@ -12253,14 +11748,14 @@ function GridCell({
|
|
|
12253
11748
|
}
|
|
12254
11749
|
),
|
|
12255
11750
|
answered ? null : /* @__PURE__ */ jsx44("span", { className: "text-xs text-muted-foreground", title: "nobody has answered this yet", children: "\u2014" }),
|
|
12256
|
-
|
|
11751
|
+
refusal3 ? /* @__PURE__ */ jsx44(CellRefusalNotice, { refusal: refusal3, field: field2, row, editing, typed: false }) : null
|
|
12257
11752
|
] });
|
|
12258
11753
|
}
|
|
12259
11754
|
if (editable && format?.id === "rating") {
|
|
12260
11755
|
return /* @__PURE__ */ jsxs39("span", { "data-matrx-cell-control": "", className: "relative flex h-full w-full flex-wrap items-center gap-1.5", children: [
|
|
12261
11756
|
/* @__PURE__ */ jsx44(FormattedValue, { value, format, onRate: (next) => editing?.setCell(row.id, field2.key, next), selectFirst: true }),
|
|
12262
11757
|
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
|
-
|
|
11758
|
+
refusal3 ? /* @__PURE__ */ jsx44(CellRefusalNotice, { refusal: refusal3, field: field2, row, editing, typed: false }) : null
|
|
12264
11759
|
] });
|
|
12265
11760
|
}
|
|
12266
11761
|
const openThisCell = (event) => {
|
|
@@ -12382,40 +11877,40 @@ function GridCell({
|
|
|
12382
11877
|
) : null
|
|
12383
11878
|
] }),
|
|
12384
11879
|
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
|
-
|
|
11880
|
+
refusal3 ? /* @__PURE__ */ jsx44(CellRefusalNotice, { refusal: refusal3, field: field2, row, editing, typed: true }) : null
|
|
12386
11881
|
]
|
|
12387
11882
|
}
|
|
12388
11883
|
)
|
|
12389
11884
|
);
|
|
12390
11885
|
}
|
|
12391
11886
|
function CellRefusalNotice({
|
|
12392
|
-
refusal:
|
|
11887
|
+
refusal: refusal3,
|
|
12393
11888
|
field: field2,
|
|
12394
11889
|
row,
|
|
12395
11890
|
editing,
|
|
12396
11891
|
typed: typed2
|
|
12397
11892
|
}) {
|
|
12398
11893
|
const [open, setOpen] = useState34(true);
|
|
12399
|
-
const line =
|
|
12400
|
-
const notice =
|
|
11894
|
+
const line = refusal3.unsent ? UNSENT_LINE : refusalLineForAPerson(refusal3.error);
|
|
11895
|
+
const notice = refusal3.unsent ? (
|
|
12401
11896
|
// NOT SENT, NOT REFUSED: what was typed is still in the cell; it goes again once online.
|
|
12402
11897
|
/* @__PURE__ */ jsxs39("div", { className: "flex flex-col gap-1.5 px-3 py-2 text-xs", "data-records-cell-unsent": "", children: [
|
|
12403
11898
|
/* @__PURE__ */ jsx44("span", { className: "font-medium", children: UNSENT_LINE }),
|
|
12404
|
-
/* @__PURE__ */ jsx44("span", { className: "max-w-[16rem] truncate text-muted-foreground", title: valueInALine(
|
|
11899
|
+
/* @__PURE__ */ jsx44("span", { className: "max-w-[16rem] truncate text-muted-foreground", title: valueInALine(refusal3.attempted), children: valueInALine(refusal3.attempted) }),
|
|
12405
11900
|
/* @__PURE__ */ jsxs39("span", { className: "flex flex-wrap gap-1", children: [
|
|
12406
11901
|
/* @__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
11902
|
/* @__PURE__ */ jsx44(Button19, { size: "sm", variant: "ghost", className: "h-6", "data-records-cell-discard": "", onClick: () => editing?.discard(row.id, field2.key), children: "Discard" })
|
|
12408
11903
|
] })
|
|
12409
11904
|
] })
|
|
12410
|
-
) :
|
|
11905
|
+
) : refusal3.conflict ? /* @__PURE__ */ jsx44(
|
|
12411
11906
|
RefusalNotice,
|
|
12412
11907
|
{
|
|
12413
|
-
error:
|
|
11908
|
+
error: refusal3.error,
|
|
12414
11909
|
className: "py-1.5 text-left",
|
|
12415
11910
|
actions: /* @__PURE__ */ jsxs39("span", { className: "flex flex-col gap-1", "data-refusal-conflict": "", children: [
|
|
12416
11911
|
/* @__PURE__ */ jsxs39("span", { className: "text-[11px]", children: [
|
|
12417
11912
|
"Theirs: ",
|
|
12418
|
-
/* @__PURE__ */ jsx44("strong", { children: formatTheirs(
|
|
11913
|
+
/* @__PURE__ */ jsx44("strong", { children: formatTheirs(refusal3.conflict, field2.key) })
|
|
12419
11914
|
] }),
|
|
12420
11915
|
/* @__PURE__ */ jsxs39("span", { className: "flex flex-wrap gap-1", children: [
|
|
12421
11916
|
/* @__PURE__ */ jsx44(Button19, { size: "sm", variant: "outline", onClick: () => editing?.retry(row.id, field2.key), children: "Try again" }),
|
|
@@ -12426,7 +11921,7 @@ function CellRefusalNotice({
|
|
|
12426
11921
|
) : /* @__PURE__ */ jsx44(
|
|
12427
11922
|
RefusalNotice,
|
|
12428
11923
|
{
|
|
12429
|
-
error:
|
|
11924
|
+
error: refusal3.error,
|
|
12430
11925
|
className: "py-1.5 text-left",
|
|
12431
11926
|
...typed2 ? { onKeepEditing: () => editing?.keepEditing(row.id, field2.key) } : {},
|
|
12432
11927
|
onDiscard: () => editing?.discard(row.id, field2.key)
|
|
@@ -12440,8 +11935,8 @@ function CellRefusalNotice({
|
|
|
12440
11935
|
"data-records-cell-refusal-line": "",
|
|
12441
11936
|
title: line,
|
|
12442
11937
|
"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 ${
|
|
11938
|
+
"data-records-cell-unsent-mark": refusal3.unsent ? "" : void 0,
|
|
11939
|
+
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
11940
|
children: "!"
|
|
12446
11941
|
}
|
|
12447
11942
|
) }),
|
|
@@ -13090,7 +12585,7 @@ function MergeRecordDialog({ tableId, record, open, onOpenChange, onMerged }) {
|
|
|
13090
12585
|
const records = useRecords3(tableId, { pageSize: 200 });
|
|
13091
12586
|
const [other, setOther] = useState37(null);
|
|
13092
12587
|
const [busy, setBusy] = useState37(false);
|
|
13093
|
-
const [
|
|
12588
|
+
const [refusal3, setRefusal] = useState37(null);
|
|
13094
12589
|
const options = useMemo15(
|
|
13095
12590
|
() => (records.data?.rows ?? []).filter((row) => row.id !== record.id).map((row) => ({ value: row.id, label: rowNameIn(table.data ?? null, row) })),
|
|
13096
12591
|
[records.data, record.id, table.data]
|
|
@@ -13160,7 +12655,7 @@ function MergeRecordDialog({ tableId, record, open, onOpenChange, onMerged }) {
|
|
|
13160
12655
|
ariaLabel: "Record to merge"
|
|
13161
12656
|
}
|
|
13162
12657
|
),
|
|
13163
|
-
|
|
12658
|
+
refusal3 ? /* @__PURE__ */ jsx47(RefusalNotice, { error: refusal3 }) : null,
|
|
13164
12659
|
/* @__PURE__ */ jsxs42(DialogFooter, { children: [
|
|
13165
12660
|
/* @__PURE__ */ jsx47(Button21, { variant: "ghost", size: "sm", onClick: () => close(false), disabled: busy, children: "Cancel" }),
|
|
13166
12661
|
/* @__PURE__ */ jsx47(Button21, { size: "sm", onClick: () => void merge(), disabled: !other || busy, "data-records-merge-go": "", children: busy ? "Merging\u2026" : "Merge" })
|
|
@@ -13344,7 +12839,7 @@ function useGridColours(args) {
|
|
|
13344
12839
|
[client, tableId, decorations, notify]
|
|
13345
12840
|
);
|
|
13346
12841
|
const idOf = useCallback12((key) => fields.find((f) => f.key === key), [fields]);
|
|
13347
|
-
const
|
|
12842
|
+
const refusal3 = mayColour ? void 0 : whyNot;
|
|
13348
12843
|
const headerItem = useCallback12(
|
|
13349
12844
|
(columnKey) => {
|
|
13350
12845
|
if (!enabled) return null;
|
|
@@ -13359,7 +12854,7 @@ function useGridColours(args) {
|
|
|
13359
12854
|
id: "col-colour",
|
|
13360
12855
|
label: "Colour by\u2026",
|
|
13361
12856
|
icon: "palette",
|
|
13362
|
-
disabledReason:
|
|
12857
|
+
disabledReason: refusal3,
|
|
13363
12858
|
submenu: [
|
|
13364
12859
|
byThis ? {
|
|
13365
12860
|
id: "col-colour-off",
|
|
@@ -13395,7 +12890,7 @@ function useGridColours(args) {
|
|
|
13395
12890
|
]
|
|
13396
12891
|
};
|
|
13397
12892
|
},
|
|
13398
|
-
[enabled, idOf, decorations.data,
|
|
12893
|
+
[enabled, idOf, decorations.data, refusal3, write]
|
|
13399
12894
|
);
|
|
13400
12895
|
const cellItem = useCallback12(
|
|
13401
12896
|
(rowId, columnKey) => {
|
|
@@ -13407,7 +12902,7 @@ function useGridColours(args) {
|
|
|
13407
12902
|
id: "cell-highlight",
|
|
13408
12903
|
label: "Highlight cell",
|
|
13409
12904
|
icon: "palette",
|
|
13410
|
-
disabledReason:
|
|
12905
|
+
disabledReason: refusal3,
|
|
13411
12906
|
submenu: swatches(
|
|
13412
12907
|
"cell-highlight",
|
|
13413
12908
|
current,
|
|
@@ -13415,7 +12910,7 @@ function useGridColours(args) {
|
|
|
13415
12910
|
)
|
|
13416
12911
|
};
|
|
13417
12912
|
},
|
|
13418
|
-
[enabled, idOf, decorations.data,
|
|
12913
|
+
[enabled, idOf, decorations.data, refusal3, write]
|
|
13419
12914
|
);
|
|
13420
12915
|
const cellsItem = useCallback12(
|
|
13421
12916
|
(cells) => {
|
|
@@ -13425,7 +12920,7 @@ function useGridColours(args) {
|
|
|
13425
12920
|
id: "sel-highlight",
|
|
13426
12921
|
label: `Highlight ${n} cells`,
|
|
13427
12922
|
icon: "palette",
|
|
13428
|
-
disabledReason:
|
|
12923
|
+
disabledReason: refusal3,
|
|
13429
12924
|
submenu: swatches("sel-highlight", void 0, (color) => {
|
|
13430
12925
|
void (async () => {
|
|
13431
12926
|
let kept = 0;
|
|
@@ -13445,7 +12940,7 @@ function useGridColours(args) {
|
|
|
13445
12940
|
})
|
|
13446
12941
|
};
|
|
13447
12942
|
},
|
|
13448
|
-
[enabled, idOf,
|
|
12943
|
+
[enabled, idOf, refusal3, client, tableId, decorations, notify]
|
|
13449
12944
|
);
|
|
13450
12945
|
const rowItem = useCallback12(
|
|
13451
12946
|
(rowId) => {
|
|
@@ -13455,7 +12950,7 @@ function useGridColours(args) {
|
|
|
13455
12950
|
id: "row-highlight",
|
|
13456
12951
|
label: "Highlight row",
|
|
13457
12952
|
icon: "palette",
|
|
13458
|
-
disabledReason:
|
|
12953
|
+
disabledReason: refusal3,
|
|
13459
12954
|
submenu: swatches(
|
|
13460
12955
|
"row-highlight",
|
|
13461
12956
|
current,
|
|
@@ -13463,7 +12958,7 @@ function useGridColours(args) {
|
|
|
13463
12958
|
)
|
|
13464
12959
|
};
|
|
13465
12960
|
},
|
|
13466
|
-
[enabled, decorations.data,
|
|
12961
|
+
[enabled, decorations.data, refusal3, write]
|
|
13467
12962
|
);
|
|
13468
12963
|
const dialogs = enabled ? /* @__PURE__ */ jsx48(
|
|
13469
12964
|
ColourRulesDialog,
|
|
@@ -14235,7 +13730,7 @@ function stepOf(step2, original) {
|
|
|
14235
13730
|
return { field: field2, set: "value", value: step2.value };
|
|
14236
13731
|
}
|
|
14237
13732
|
function actionOf(draft, original) {
|
|
14238
|
-
const
|
|
13733
|
+
const base2 = {
|
|
14239
13734
|
...draft.id ? { id: draft.id } : {},
|
|
14240
13735
|
name: draft.name.trim(),
|
|
14241
13736
|
kind: draft.kind,
|
|
@@ -14243,9 +13738,9 @@ function actionOf(draft, original) {
|
|
|
14243
13738
|
...draft.color ? { color: draft.color } : {},
|
|
14244
13739
|
...draft.icon ? { icon: draft.icon } : {}
|
|
14245
13740
|
};
|
|
14246
|
-
if (draft.kind === "agent") return { ...
|
|
13741
|
+
if (draft.kind === "agent") return { ...base2, prompt: draft.prompt };
|
|
14247
13742
|
return {
|
|
14248
|
-
...
|
|
13743
|
+
...base2,
|
|
14249
13744
|
steps: draft.steps.map((s, i) => stepOf(s, original?.steps?.[i]))
|
|
14250
13745
|
};
|
|
14251
13746
|
}
|
|
@@ -15511,19 +15006,19 @@ function planPastedBlock(args) {
|
|
|
15511
15006
|
accepted[key] = judged.value;
|
|
15512
15007
|
}
|
|
15513
15008
|
const predicted = predictValueRefusals(args.fields, accepted);
|
|
15514
|
-
for (const
|
|
15515
|
-
const key =
|
|
15009
|
+
for (const refusal3 of predicted) {
|
|
15010
|
+
const key = refusal3.field_key;
|
|
15516
15011
|
if (key === void 0) continue;
|
|
15517
15012
|
const cell2 = built.find((b) => b.key === key && b.refusal === null);
|
|
15518
15013
|
if (!cell2) continue;
|
|
15519
|
-
cell2.refusal =
|
|
15014
|
+
cell2.refusal = refusal3.message;
|
|
15520
15015
|
cell2.value = null;
|
|
15521
15016
|
delete accepted[key];
|
|
15522
15017
|
refusals.push({
|
|
15523
15018
|
fromLine,
|
|
15524
15019
|
column: fieldName(byKey.get(key) ?? { key }),
|
|
15525
15020
|
raw: cell2.raw,
|
|
15526
|
-
why:
|
|
15021
|
+
why: refusal3.message
|
|
15527
15022
|
});
|
|
15528
15023
|
}
|
|
15529
15024
|
cells += Object.keys(accepted).length;
|
|
@@ -15727,8 +15222,8 @@ function useMergedGridControls(args) {
|
|
|
15727
15222
|
setHeld(null);
|
|
15728
15223
|
}, [keptKey]);
|
|
15729
15224
|
const order = useMemo21(() => {
|
|
15730
|
-
const
|
|
15731
|
-
const known = columnsInKeptOrder(fieldKeys,
|
|
15225
|
+
const base2 = held?.order ?? columnsInKeptOrder(fieldKeys, keptOrder);
|
|
15226
|
+
const known = columnsInKeptOrder(fieldKeys, base2);
|
|
15732
15227
|
if (frozenKeys.size === 0) return known;
|
|
15733
15228
|
return [...known.filter((k) => frozenKeys.has(k)), ...known.filter((k) => !frozenKeys.has(k))];
|
|
15734
15229
|
}, [held, fieldKeys, keptOrder, frozenKeys]);
|
|
@@ -15784,10 +15279,10 @@ function useMergedGridControls(args) {
|
|
|
15784
15279
|
return;
|
|
15785
15280
|
}
|
|
15786
15281
|
let cancelled = false;
|
|
15787
|
-
const [keys, filters,
|
|
15282
|
+
const [keys, filters, base2, searched] = JSON.parse(countQuestionKey);
|
|
15788
15283
|
for (const key of keys) {
|
|
15789
15284
|
const { [key]: _own, ...others } = filters;
|
|
15790
|
-
const asked2 = storeQuestion(fieldsRef.current,
|
|
15285
|
+
const asked2 = storeQuestion(fieldsRef.current, base2 ?? void 0, others);
|
|
15791
15286
|
void (0, askOnce_exports.askOnce)(
|
|
15792
15287
|
client,
|
|
15793
15288
|
`value_counts:${tableId}:${key}:${searched}:${JSON.stringify(asked2.filter ?? null)}`,
|
|
@@ -16403,9 +15898,9 @@ function readersThrough(fields, key) {
|
|
|
16403
15898
|
});
|
|
16404
15899
|
}
|
|
16405
15900
|
function backLinkSentence(column, readers = [], tableName2 = null) {
|
|
16406
|
-
const
|
|
16407
|
-
if (readers.length === 0) return
|
|
16408
|
-
return `${readersSentence(readers.length, tableName2)} ${
|
|
15901
|
+
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.`;
|
|
15902
|
+
if (readers.length === 0) return base2;
|
|
15903
|
+
return `${readersSentence(readers.length, tableName2)} ${base2}`;
|
|
16409
15904
|
}
|
|
16410
15905
|
function afterMenuLayerCloses(next) {
|
|
16411
15906
|
if (typeof window === "undefined") return next();
|
|
@@ -17744,8 +17239,8 @@ function useDrillDefinition(source) {
|
|
|
17744
17239
|
}, [client, key]);
|
|
17745
17240
|
return state.key === key ? { def: state.def, error: state.error } : { def: null, error: null };
|
|
17746
17241
|
}
|
|
17747
|
-
function drillWhere(
|
|
17748
|
-
const where = { ...
|
|
17242
|
+
function drillWhere(base2, trail, booleans) {
|
|
17243
|
+
const where = { ...base2 ?? {} };
|
|
17749
17244
|
for (const w of trail) {
|
|
17750
17245
|
const { key, grain } = parseDimensionRef2(w.dim);
|
|
17751
17246
|
if (grain) where[w.dim] = w.value;
|
|
@@ -17924,10 +17419,10 @@ function useDrill(args) {
|
|
|
17924
17419
|
const booleans = useMemo25(() => new Set((def?.dimensions ?? []).filter((d) => d.kind === "boolean").map((d) => d.key)), [def]);
|
|
17925
17420
|
const baseKey = JSON.stringify(args.base ?? []);
|
|
17926
17421
|
const filter = useMemo25(() => {
|
|
17927
|
-
const
|
|
17928
|
-
if (
|
|
17422
|
+
const base2 = JSON.parse(baseKey);
|
|
17423
|
+
if (base2.length === 0) return args.filter;
|
|
17929
17424
|
const out = { ...args.filter ?? {} };
|
|
17930
|
-
for (const b of
|
|
17425
|
+
for (const b of base2) out[b.key] = b.value;
|
|
17931
17426
|
return out;
|
|
17932
17427
|
}, [args.filter, baseKey]);
|
|
17933
17428
|
const where = useMemo25(() => drillWhere(filter, question.where, booleans), [filter, question.where, booleans]);
|
|
@@ -18056,17 +17551,17 @@ function trailClause(fields, w) {
|
|
|
18056
17551
|
}
|
|
18057
17552
|
return { key, value: w.value, field: field2 };
|
|
18058
17553
|
}
|
|
18059
|
-
function filterWithTrail(fields,
|
|
18060
|
-
if (trail.length === 0) return
|
|
18061
|
-
if (!
|
|
18062
|
-
const flat = { ...
|
|
17554
|
+
function filterWithTrail(fields, base2, trail) {
|
|
17555
|
+
if (trail.length === 0) return base2;
|
|
17556
|
+
if (!base2 || !isRuleFilter2(base2)) {
|
|
17557
|
+
const flat = { ...base2 ?? {} };
|
|
18063
17558
|
for (const w of trail) {
|
|
18064
17559
|
const clause = trailClause(fields, w);
|
|
18065
17560
|
flat[clause.key] = clause.value;
|
|
18066
17561
|
}
|
|
18067
17562
|
return flat;
|
|
18068
17563
|
}
|
|
18069
|
-
const args = [
|
|
17564
|
+
const args = [base2];
|
|
18070
17565
|
for (const w of trail) {
|
|
18071
17566
|
const clause = trailClause(fields, w);
|
|
18072
17567
|
if (!clause.field) continue;
|
|
@@ -18080,14 +17575,14 @@ function filterWithTrail(fields, base, trail) {
|
|
|
18080
17575
|
}
|
|
18081
17576
|
return { op: "and", args };
|
|
18082
17577
|
}
|
|
18083
|
-
function filterWithWindow(fields,
|
|
18084
|
-
if (!
|
|
17578
|
+
function filterWithWindow(fields, base2, key, range) {
|
|
17579
|
+
if (!base2 || !isRuleFilter2(base2)) return { ...base2 ?? {}, [key]: { from: range.from, to: range.to } };
|
|
18085
17580
|
const field2 = fields.find((f) => f.key === key);
|
|
18086
|
-
if (!field2) return
|
|
17581
|
+
if (!field2) return base2;
|
|
18087
17582
|
const ref = { field: field2.id };
|
|
18088
17583
|
return {
|
|
18089
17584
|
op: "and",
|
|
18090
|
-
args: [
|
|
17585
|
+
args: [base2, { op: "gte", args: [ref, { const: range.from }] }, { op: "lt", args: [ref, { const: range.to }] }]
|
|
18091
17586
|
};
|
|
18092
17587
|
}
|
|
18093
17588
|
function useGridDrillQuestion(args) {
|
|
@@ -18769,7 +18264,7 @@ function columnForField(field2, editing, mayWriteRow, whyNotRow, look, onAskWhoC
|
|
|
18769
18264
|
...look?.frozen ? { frozen: true, width: Math.max(FROZEN_COLUMN_WIDTH, defaultColumnWidth(field2)) } : { width: defaultColumnWidth(field2) },
|
|
18770
18265
|
// A column that holds numbers filters as numbers (=, <, >, between) — the record number too,
|
|
18771
18266
|
// 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" :
|
|
18267
|
+
filter: filterRefusal(field2) !== null ? false : editorKindFor(field2) === "select" || editorKindFor(field2) === "multi_select" ? "select" : holdsNumbers2(field2) ? "number" : "auto",
|
|
18773
18268
|
// THE MENU'S VALUE LIST WEARS THE CHOICES' COLOURS (lane CELL-EDITORS, night walk 2026-10-06): the
|
|
18774
18269
|
// same chip the cell draws, never bare words beside a coloured column.
|
|
18775
18270
|
...editorKindFor(field2) === "select" || editorKindFor(field2) === "multi_select" ? { filterValueClass: (value, label) => choiceChipLookOf(field2, value, label).className } : {},
|
|
@@ -18896,6 +18391,18 @@ function withTypeMark(field2, header) {
|
|
|
18896
18391
|
// src/ReverseColumns.tsx
|
|
18897
18392
|
import { useCallback as useCallback20, useEffect as useEffect44, useMemo as useMemo27, useRef as useRef29, useState as useState55, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
18898
18393
|
import { isReverseField } from "@ai-matrx/records";
|
|
18394
|
+
|
|
18395
|
+
// src/groupReads.ts
|
|
18396
|
+
import {
|
|
18397
|
+
REVERSE_CELL_CHIPS,
|
|
18398
|
+
choiceFieldKeys,
|
|
18399
|
+
groupFactMeasures,
|
|
18400
|
+
groupedPageSort,
|
|
18401
|
+
isPlainGrouping,
|
|
18402
|
+
summaryBarMeasures
|
|
18403
|
+
} from "@ai-matrx/records/first-page";
|
|
18404
|
+
|
|
18405
|
+
// src/ReverseColumns.tsx
|
|
18899
18406
|
import { useFields as useFields6, useOptionalRecordsClient as useOptionalRecordsClient11, useReverseColumns as useReverseColumns3, useReverseLinks, useTable as useTable4 } from "@ai-matrx/records/react";
|
|
18900
18407
|
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
18408
|
import { Fragment as Fragment19, jsx as jsx65, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
@@ -19356,10 +18863,10 @@ function PastePreview({
|
|
|
19356
18863
|
/* @__PURE__ */ jsx67(PlanTable, { plan }),
|
|
19357
18864
|
plan.refusals.length > 0 ? /* @__PURE__ */ jsxs62("div", { "data-matrx-paste-refusals": true, className: "flex flex-col gap-1", children: [
|
|
19358
18865
|
/* @__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:
|
|
18866
|
+
/* @__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: [
|
|
18867
|
+
/* @__PURE__ */ jsx67("span", { className: "font-medium", children: refusal3.fromLine > 0 ? `Row ${refusal3.fromLine}, ${refusal3.column}` : refusal3.column }),
|
|
19361
18868
|
" \u2014 ",
|
|
19362
|
-
|
|
18869
|
+
refusal3.why
|
|
19363
18870
|
] }, index)) }),
|
|
19364
18871
|
plan.refusals.length > 12 ? /* @__PURE__ */ jsxs62("p", { className: "text-xs text-muted-foreground", children: [
|
|
19365
18872
|
plan.refusals.length - 12,
|
|
@@ -19836,8 +19343,8 @@ function offerDownload(name, text, type = "text/csv") {
|
|
|
19836
19343
|
return true;
|
|
19837
19344
|
}
|
|
19838
19345
|
function refusedFileName(sourceName) {
|
|
19839
|
-
const
|
|
19840
|
-
return `${
|
|
19346
|
+
const base2 = (sourceName ?? "import").replace(/\.(csv|xlsx)$/i, "");
|
|
19347
|
+
return `${base2} \u2014 rows not added.csv`;
|
|
19841
19348
|
}
|
|
19842
19349
|
|
|
19843
19350
|
// src/ImportWizard.tsx
|
|
@@ -21291,11 +20798,11 @@ function cellWords(raw) {
|
|
|
21291
20798
|
function uniqueLabels(raw) {
|
|
21292
20799
|
const seen = /* @__PURE__ */ new Map();
|
|
21293
20800
|
return raw.map((label, index) => {
|
|
21294
|
-
const
|
|
21295
|
-
const key =
|
|
20801
|
+
const base2 = label.trim() || `Column ${index + 1}`;
|
|
20802
|
+
const key = base2.toLowerCase();
|
|
21296
20803
|
const count = (seen.get(key) ?? 0) + 1;
|
|
21297
20804
|
seen.set(key, count);
|
|
21298
|
-
return count === 1 ?
|
|
20805
|
+
return count === 1 ? base2 : `${base2} ${count}`;
|
|
21299
20806
|
});
|
|
21300
20807
|
}
|
|
21301
20808
|
function rowsOf(headers, matrix) {
|
|
@@ -21356,7 +20863,7 @@ function recordsFromPairs(pairs) {
|
|
|
21356
20863
|
if (current.size > 0) records.push(current);
|
|
21357
20864
|
return records;
|
|
21358
20865
|
}
|
|
21359
|
-
function shapeFromRecords(records,
|
|
20866
|
+
function shapeFromRecords(records, base2, from) {
|
|
21360
20867
|
const order = [];
|
|
21361
20868
|
for (const r of records) for (const k of r.keys()) if (!order.some((o) => o.toLowerCase() === k.toLowerCase())) order.push(k);
|
|
21362
20869
|
const headers = uniqueLabels(order);
|
|
@@ -21369,7 +20876,7 @@ function shapeFromRecords(records, base, from) {
|
|
|
21369
20876
|
return row;
|
|
21370
20877
|
});
|
|
21371
20878
|
return {
|
|
21372
|
-
...
|
|
20879
|
+
...base2,
|
|
21373
20880
|
kind: "key_value",
|
|
21374
20881
|
headers,
|
|
21375
20882
|
rows,
|
|
@@ -21948,7 +21455,7 @@ function valueListKind(field2) {
|
|
|
21948
21455
|
if (kind === "text" || kind === "long_text" || kind === "email" || kind === "phone" || kind === "url") return "words";
|
|
21949
21456
|
if (kind === "datetime" || kind === "date") return "days";
|
|
21950
21457
|
if (kind === "checkbox") return "yesno";
|
|
21951
|
-
if (
|
|
21458
|
+
if (holdsNumbers2(field2) || kind === "rating") return "numbers";
|
|
21952
21459
|
return "loaded";
|
|
21953
21460
|
}
|
|
21954
21461
|
function noValueList(columnId2) {
|
|
@@ -22214,35 +21721,35 @@ function useGridUndo(args) {
|
|
|
22214
21721
|
if (!step2) return;
|
|
22215
21722
|
setBusy(true);
|
|
22216
21723
|
const changes = changesFor(step2, direction, known.current);
|
|
22217
|
-
let
|
|
21724
|
+
let refusal3 = null;
|
|
22218
21725
|
if (direction === "redo" && (step2.created?.length ?? 0) > 0) {
|
|
22219
21726
|
const answers = await Promise.all((step2.created ?? []).map((id) => client.recordRestore({ record_id: id })));
|
|
22220
21727
|
const failed = answers.find((a) => !a.ok);
|
|
22221
|
-
if (failed && !failed.ok)
|
|
21728
|
+
if (failed && !failed.ok) refusal3 = failed.error;
|
|
22222
21729
|
}
|
|
22223
|
-
if (!
|
|
21730
|
+
if (!refusal3 && step2.retiredField) {
|
|
22224
21731
|
const fieldId = step2.retiredField.fieldId;
|
|
22225
21732
|
const done = direction === "undo" ? await client.fieldRestore({ field_id: fieldId }) : await client.fieldRetire({ field_id: fieldId });
|
|
22226
|
-
if (!done.ok)
|
|
21733
|
+
if (!done.ok) refusal3 = done.error;
|
|
22227
21734
|
else tableShapeChanged6(tableId);
|
|
22228
21735
|
}
|
|
22229
|
-
if (!
|
|
21736
|
+
if (!refusal3 && changes.length > 0) {
|
|
22230
21737
|
const done = await (0, recordVersions_exports.changeRecordsAt)(client, { table_id: tableId, changes });
|
|
22231
|
-
if (!done.ok)
|
|
21738
|
+
if (!done.ok) refusal3 = done.error;
|
|
22232
21739
|
else {
|
|
22233
21740
|
for (const result of done.data ?? []) if (result.op === "update") known.current.set(result.id, result.version);
|
|
22234
21741
|
onVersions?.((done.data ?? []).flatMap((r) => r.op === "update" ? [{ id: r.id, version: r.version }] : []));
|
|
22235
21742
|
}
|
|
22236
21743
|
}
|
|
22237
|
-
if (!
|
|
21744
|
+
if (!refusal3 && direction === "undo" && (step2.archived?.length ?? 0) > 0) {
|
|
22238
21745
|
const answers = await Promise.all((step2.archived ?? []).map((id) => client.recordRestore({ record_id: id })));
|
|
22239
21746
|
const failed = answers.find((a) => !a.ok);
|
|
22240
|
-
if (failed && !failed.ok)
|
|
21747
|
+
if (failed && !failed.ok) refusal3 = failed.error;
|
|
22241
21748
|
}
|
|
22242
21749
|
setBusy(false);
|
|
22243
|
-
if (
|
|
22244
|
-
setNotice({ says: `${direction === "undo" ? "Undo" : "Redo"} changed nothing: ${refusalSentence(
|
|
22245
|
-
if ((0, recordVersions_exports.isChangedElsewhere)(
|
|
21750
|
+
if (refusal3) {
|
|
21751
|
+
setNotice({ says: `${direction === "undo" ? "Undo" : "Redo"} changed nothing: ${refusalSentence(refusal3)}`, refusal: refusal3, canUndo: false });
|
|
21752
|
+
if ((0, recordVersions_exports.isChangedElsewhere)(refusal3)) reload();
|
|
22246
21753
|
return;
|
|
22247
21754
|
}
|
|
22248
21755
|
forget(step2.cells.map((c) => ({ rowId: c.rowId, key: c.key })));
|
|
@@ -22973,7 +22480,7 @@ function useGridBulk(args) {
|
|
|
22973
22480
|
const client = useRecordsClient37();
|
|
22974
22481
|
const { tableId, rows, fields, noun, nounPlural, reload, forget, pushUndo: pushUndo2, versions } = args;
|
|
22975
22482
|
const [busy, setBusy] = useState62(false);
|
|
22976
|
-
const [
|
|
22483
|
+
const [refusal3, setRefusal] = useState62(null);
|
|
22977
22484
|
const send = useCallback26(
|
|
22978
22485
|
async (changes) => {
|
|
22979
22486
|
setBusy(true);
|
|
@@ -23037,7 +22544,7 @@ function useGridBulk(args) {
|
|
|
23037
22544
|
},
|
|
23038
22545
|
[send, rows, pushUndo2, reload, noun, nounPlural]
|
|
23039
22546
|
);
|
|
23040
|
-
return { busy, refusal:
|
|
22547
|
+
return { busy, refusal: refusal3, clearRefusal: () => setRefusal(null), apply, duplicate, archive };
|
|
23041
22548
|
}
|
|
23042
22549
|
function BulkActions({
|
|
23043
22550
|
ids,
|
|
@@ -23158,6 +22665,31 @@ import { useEffect as useEffect52, useMemo as useMemo34, useRef as useRef35, use
|
|
|
23158
22665
|
import { useRecordsClient as useRecordsClient38 } from "@ai-matrx/records/react";
|
|
23159
22666
|
import { stableFilterKey as stableFilterKey2 } from "@ai-matrx/records";
|
|
23160
22667
|
import { Button as Button43, ConfirmDialog as ConfirmDialog4, Popover as Popover9, PopoverContent as PopoverContent9, PopoverTrigger as PopoverTrigger9, cn as cn38 } from "@ai-matrx/design-system";
|
|
22668
|
+
|
|
22669
|
+
// src/views.ts
|
|
22670
|
+
import {
|
|
22671
|
+
STORE_KEEPS_TIMELINE as STORE_KEEPS_TIMELINE2,
|
|
22672
|
+
STORE_KEPT_LAYOUTS as STORE_KEPT_LAYOUTS2,
|
|
22673
|
+
storeKeepsLayout as storeKeepsLayout2,
|
|
22674
|
+
VIEW_LAYOUTS,
|
|
22675
|
+
LAYOUT_LABEL,
|
|
22676
|
+
wordsList,
|
|
22677
|
+
VIEW_NEEDS,
|
|
22678
|
+
freeColumnName,
|
|
22679
|
+
viewOrderOf,
|
|
22680
|
+
defaultViewOf,
|
|
22681
|
+
LAYOUT_FIELD_KIND,
|
|
22682
|
+
PAGE_VIEWS,
|
|
22683
|
+
PAGE_VIEW_LABEL,
|
|
22684
|
+
pageViewFromParam,
|
|
22685
|
+
unknownViewLine,
|
|
22686
|
+
makeDefaultLabel,
|
|
22687
|
+
designateView,
|
|
22688
|
+
viewPatchFor
|
|
22689
|
+
} from "@ai-matrx/records/views";
|
|
22690
|
+
var { viewDocument, viewFromRow, declareView, saveViewPatch, viewPatchDocument } = boundViews;
|
|
22691
|
+
|
|
22692
|
+
// src/handOrder.tsx
|
|
23161
22693
|
import { jsx as jsx76, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
23162
22694
|
function sortArrow(direction) {
|
|
23163
22695
|
return direction === "asc" ? "\u2191" : "\u2193";
|
|
@@ -25716,6 +25248,11 @@ import {
|
|
|
25716
25248
|
useEntityWrite,
|
|
25717
25249
|
useOptionalEntityScope
|
|
25718
25250
|
} from "@ai-matrx/records/entity/react";
|
|
25251
|
+
|
|
25252
|
+
// src/entityQuery.ts
|
|
25253
|
+
import { entityChartQuestion, entityTableQuery } from "@ai-matrx/records/first-page";
|
|
25254
|
+
|
|
25255
|
+
// src/entityTable.tsx
|
|
25719
25256
|
import { Fragment as Fragment27, jsx as jsx78 } from "react/jsx-runtime";
|
|
25720
25257
|
function EntityDataScope({ children }) {
|
|
25721
25258
|
const above = useOptionalEntityScope();
|
|
@@ -26446,19 +25983,19 @@ function fieldsForNewColumns(columns) {
|
|
|
26446
25983
|
let key = tokenFor(column.label) || `column_${i + 1}`;
|
|
26447
25984
|
while (keys.has(key)) key = `${key}_${i + 1}`;
|
|
26448
25985
|
keys.add(key);
|
|
26449
|
-
const
|
|
25986
|
+
const base2 = { key, label: column.label, sort: (i + 1) * 10, required: false };
|
|
26450
25987
|
switch (column.type) {
|
|
26451
25988
|
case "date":
|
|
26452
|
-
return { ...
|
|
25989
|
+
return { ...base2, type: "datetime", kind: "date" };
|
|
26453
25990
|
case "datetime":
|
|
26454
|
-
return { ...
|
|
25991
|
+
return { ...base2, type: "datetime", kind: "datetime" };
|
|
26455
25992
|
case "currency":
|
|
26456
|
-
return { ...
|
|
25993
|
+
return { ...base2, type: "currency", unit: "$" };
|
|
26457
25994
|
case "select":
|
|
26458
25995
|
case "multi_select":
|
|
26459
|
-
return { ...
|
|
25996
|
+
return { ...base2, type: column.type, multi: column.type === "multi_select", options: column.options ?? [] };
|
|
26460
25997
|
default:
|
|
26461
|
-
return { ...
|
|
25998
|
+
return { ...base2, type: column.type };
|
|
26462
25999
|
}
|
|
26463
26000
|
});
|
|
26464
26001
|
}
|
|
@@ -27124,15 +26661,15 @@ function objectActionForKey(actions, event) {
|
|
|
27124
26661
|
const id = Object.keys(TABLE_ACTION_KEYS).find((k) => TABLE_ACTION_KEYS[k].code === event.code);
|
|
27125
26662
|
return id ? actions.find((a) => a.id === id) ?? null : null;
|
|
27126
26663
|
}
|
|
27127
|
-
function action(
|
|
27128
|
-
const chord = TABLE_ACTION_KEYS[
|
|
27129
|
-
if (chord &&
|
|
26664
|
+
function action(base2, needs, input, perform) {
|
|
26665
|
+
const chord = TABLE_ACTION_KEYS[base2.id];
|
|
26666
|
+
if (chord && base2.shortcut === void 0) base2 = { ...base2, shortcut: chord.label };
|
|
27130
26667
|
const refused = rightsReason(input.rights, needs, input.table);
|
|
27131
|
-
if (refused !== null) return { ...
|
|
26668
|
+
if (refused !== null) return { ...base2, disabledReason: refused, run: NOOP };
|
|
27132
26669
|
if (perform === void 0) {
|
|
27133
|
-
return { ...
|
|
26670
|
+
return { ...base2, disabledReason: input.host.unavailableReasons?.[base2.id] ?? ACTION_NOT_HERE_REASON, run: NOOP };
|
|
27134
26671
|
}
|
|
27135
|
-
return { ...
|
|
26672
|
+
return { ...base2, run: perform };
|
|
27136
26673
|
}
|
|
27137
26674
|
function bind(handler, table) {
|
|
27138
26675
|
return handler ? () => handler(table) : void 0;
|
|
@@ -27203,9 +26740,9 @@ function tableActions(input) {
|
|
|
27203
26740
|
];
|
|
27204
26741
|
return withExtensions(built, host.extend ? host.extend(table, input.rights) : []);
|
|
27205
26742
|
}
|
|
27206
|
-
function withExtensions(
|
|
27207
|
-
if (extra.length === 0) return [...
|
|
27208
|
-
const seen = new Set(
|
|
26743
|
+
function withExtensions(base2, extra) {
|
|
26744
|
+
if (extra.length === 0) return [...base2];
|
|
26745
|
+
const seen = new Set(base2.map((a) => a.id));
|
|
27209
26746
|
for (const entry of extra) {
|
|
27210
26747
|
if (entry.group === "danger") {
|
|
27211
26748
|
throw new Error(`Object action "${entry.id}": the danger group is closed to extensions.`);
|
|
@@ -27220,7 +26757,7 @@ function withExtensions(base, extra) {
|
|
|
27220
26757
|
}
|
|
27221
26758
|
const out = [];
|
|
27222
26759
|
for (const group of OBJECT_ACTION_GROUPS) {
|
|
27223
|
-
out.push(...
|
|
26760
|
+
out.push(...base2.filter((a) => a.group === group.id), ...extra.filter((a) => a.group === group.id));
|
|
27224
26761
|
}
|
|
27225
26762
|
return out;
|
|
27226
26763
|
}
|
|
@@ -27426,7 +26963,7 @@ function ArchivedBuiltOn({ tableId, onRestored }) {
|
|
|
27426
26963
|
const [things, setThings] = useState68(null);
|
|
27427
26964
|
const [error, setError] = useState68(null);
|
|
27428
26965
|
const [restoring, setRestoring] = useState68(null);
|
|
27429
|
-
const [
|
|
26966
|
+
const [refusal3, setRefusal] = useState68(null);
|
|
27430
26967
|
const [said2, setSaid] = useState68(null);
|
|
27431
26968
|
const read = useCallback30(async () => {
|
|
27432
26969
|
const [forms, checklists] = await Promise.all([
|
|
@@ -27479,7 +27016,7 @@ function ArchivedBuiltOn({ tableId, onRestored }) {
|
|
|
27479
27016
|
" \xB7 archived ",
|
|
27480
27017
|
archivedWhen(thing.archivedAt)
|
|
27481
27018
|
] }),
|
|
27482
|
-
|
|
27019
|
+
refusal3 && refusal3.id === thing.id ? /* @__PURE__ */ jsx87(RefusalNotice, { error: refusal3.error, className: "mt-2" }) : null
|
|
27483
27020
|
] }),
|
|
27484
27021
|
thing.whyNot ? /* @__PURE__ */ jsx87("span", { className: "text-xs text-muted-foreground", children: thing.whyNot }) : /* @__PURE__ */ jsx87(
|
|
27485
27022
|
Button50,
|
|
@@ -28323,20 +27860,20 @@ function draftsFor(headers, rows) {
|
|
|
28323
27860
|
function keysFor(labels) {
|
|
28324
27861
|
const used = /* @__PURE__ */ new Set();
|
|
28325
27862
|
return labels.map((label, i) => {
|
|
28326
|
-
const
|
|
28327
|
-
let key =
|
|
27863
|
+
const base2 = tokenFor(label) === "table" && !/table/i.test(label) ? `column_${i + 1}` : tokenFor(label);
|
|
27864
|
+
let key = base2;
|
|
28328
27865
|
let n = 2;
|
|
28329
|
-
while (used.has(key)) key = `${
|
|
27866
|
+
while (used.has(key)) key = `${base2}_${n++}`;
|
|
28330
27867
|
used.add(key);
|
|
28331
27868
|
return key;
|
|
28332
27869
|
});
|
|
28333
27870
|
}
|
|
28334
27871
|
function freeName(name, taken) {
|
|
28335
27872
|
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 `${
|
|
27873
|
+
const base2 = name.trim() || "Saved table";
|
|
27874
|
+
if (!lower.has(base2.toLowerCase())) return base2;
|
|
27875
|
+
for (let n = 2; n < 100; n += 1) if (!lower.has(`${base2} ${n}`.toLowerCase())) return `${base2} ${n}`;
|
|
27876
|
+
return `${base2} ${Date.now()}`;
|
|
28340
27877
|
}
|
|
28341
27878
|
async function sha256Text(text) {
|
|
28342
27879
|
const subtle = globalThis.crypto?.subtle;
|
|
@@ -29256,11 +28793,11 @@ import { Badge as Badge14, Button as Button61, Separator as Separator8, cn as cn
|
|
|
29256
28793
|
var TableRestoreRefused = class extends Error {
|
|
29257
28794
|
refusal;
|
|
29258
28795
|
sentence;
|
|
29259
|
-
constructor(
|
|
29260
|
-
const sentence2 = refusalSentence(
|
|
28796
|
+
constructor(refusal3) {
|
|
28797
|
+
const sentence2 = refusalSentence(refusal3);
|
|
29261
28798
|
super(sentence2);
|
|
29262
28799
|
this.name = "TableRestoreRefused";
|
|
29263
|
-
this.refusal =
|
|
28800
|
+
this.refusal = refusal3;
|
|
29264
28801
|
this.sentence = sentence2;
|
|
29265
28802
|
}
|
|
29266
28803
|
};
|
|
@@ -30778,6 +30315,22 @@ function usePlatformTable(spec) {
|
|
|
30778
30315
|
return state;
|
|
30779
30316
|
}
|
|
30780
30317
|
|
|
30318
|
+
// src/viewLook.ts
|
|
30319
|
+
import { applyLook, lookDiffers, lookPart, saveToViewPlan } from "@ai-matrx/records/views";
|
|
30320
|
+
var { lookDocument, lookFromDocument, readLooks, keepLook } = boundViews;
|
|
30321
|
+
var LOOK_WORDS = {
|
|
30322
|
+
/** The reason, for a tooltip or a screen reader — never a line on the page (interface-text). */
|
|
30323
|
+
yours: "You changed how this view looks. Only you see it.",
|
|
30324
|
+
/** The visible label for the same fact. */
|
|
30325
|
+
yoursLabel: "Only you see this",
|
|
30326
|
+
saveToView: "Save to view",
|
|
30327
|
+
saveAsNew: "Save as new view",
|
|
30328
|
+
reset: "Reset to view",
|
|
30329
|
+
/** The one button your look's doors fold into when the toolbar row has no room for three. */
|
|
30330
|
+
folded: "Your look",
|
|
30331
|
+
newName: "Name for the new view"
|
|
30332
|
+
};
|
|
30333
|
+
|
|
30781
30334
|
// src/ViewSwitcher.tsx
|
|
30782
30335
|
import { useEffect as useEffect79, useMemo as useMemo55, useState as useState93 } from "react";
|
|
30783
30336
|
import { mayDrag as mayDrag4, useFields as useFields18, useRecordPage as useRecordPage2, useRecordsClient as useRecordsClient65, useTable as useTable18 } from "@ai-matrx/records/react";
|
|
@@ -31072,13 +30625,13 @@ function recordLink(tableId, recordId, origin = DEFAULT_ACTION_ORIGIN) {
|
|
|
31072
30625
|
}
|
|
31073
30626
|
var NOOP2 = () => {
|
|
31074
30627
|
};
|
|
31075
|
-
function action2(
|
|
30628
|
+
function action2(base2, needs, input, perform) {
|
|
31076
30629
|
const refused = rightsReason(input.rights, needs);
|
|
31077
|
-
if (refused !== null) return { ...
|
|
30630
|
+
if (refused !== null) return { ...base2, disabledReason: refused, run: NOOP2 };
|
|
31078
30631
|
if (perform === void 0) {
|
|
31079
|
-
return { ...
|
|
30632
|
+
return { ...base2, disabledReason: input.host.unavailableReasons?.[base2.id] ?? ACTION_NOT_HERE_REASON, run: NOOP2 };
|
|
31080
30633
|
}
|
|
31081
|
-
return { ...
|
|
30634
|
+
return { ...base2, run: perform };
|
|
31082
30635
|
}
|
|
31083
30636
|
function bind2(handler, record) {
|
|
31084
30637
|
return handler ? () => handler(record) : void 0;
|
|
@@ -33845,12 +33398,12 @@ function viewNeedFor(layout) {
|
|
|
33845
33398
|
return VIEW_NEEDS[layout];
|
|
33846
33399
|
}
|
|
33847
33400
|
function columnDeclarationFor(need, label, options, fields) {
|
|
33848
|
-
const
|
|
33401
|
+
const base2 = { label: label.trim(), sort: nextFieldSort(fields) };
|
|
33849
33402
|
if (need.starter.type === "select") {
|
|
33850
|
-
return { ...
|
|
33403
|
+
return { ...base2, parity_type: "select", options: options.map((o) => o.trim()).filter((o) => o !== "") };
|
|
33851
33404
|
}
|
|
33852
|
-
if (need.starter.type === "datetime") return { ...
|
|
33853
|
-
return { ...
|
|
33405
|
+
if (need.starter.type === "datetime") return { ...base2, parity_type: "datetime", kind: "date" };
|
|
33406
|
+
return { ...base2, parity_type: "attachment" };
|
|
33854
33407
|
}
|
|
33855
33408
|
var askedFor = /* @__PURE__ */ new Map();
|
|
33856
33409
|
var askKey = (tableId, layout) => `${tableId}:${layout}`;
|
|
@@ -34730,10 +34283,10 @@ function Board({
|
|
|
34730
34283
|
...view.endField ? { endKey: view.endField } : {},
|
|
34731
34284
|
groupKey: view.groupField ?? null,
|
|
34732
34285
|
...view.presentation?.style?.colorBy !== void 0 ? { colorKey: view.presentation.style.colorBy?.field ?? null } : {},
|
|
34733
|
-
layoutKept: remembered &&
|
|
34286
|
+
layoutKept: remembered && STORE_KEEPS_TIMELINE2,
|
|
34734
34287
|
onSettingsChange: (patch) => {
|
|
34735
34288
|
if (patch.startKey !== void 0) {
|
|
34736
|
-
onChange({ startField: patch.startKey, ...
|
|
34289
|
+
onChange({ startField: patch.startKey, ...STORE_KEEPS_TIMELINE2 ? {} : { dateField: patch.startKey } });
|
|
34737
34290
|
}
|
|
34738
34291
|
if (patch.endKey !== void 0) onChange({ endField: patch.endKey });
|
|
34739
34292
|
if (patch.groupKey !== void 0) onChange({ groupField: patch.groupKey });
|
|
@@ -35333,7 +34886,7 @@ function ArchivedView({
|
|
|
35333
34886
|
const [loading, setLoading] = useState94(true);
|
|
35334
34887
|
const [error, setError] = useState94(null);
|
|
35335
34888
|
const [restoring, setRestoring] = useState94(null);
|
|
35336
|
-
const [
|
|
34889
|
+
const [refusal3, setRefusal] = useState94(null);
|
|
35337
34890
|
useEffect80(() => {
|
|
35338
34891
|
if (laneFromHost) setLane(laneFromHost);
|
|
35339
34892
|
}, [laneFromHost]);
|
|
@@ -35410,7 +34963,7 @@ function ArchivedView({
|
|
|
35410
34963
|
/* @__PURE__ */ jsxs106("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
35411
34964
|
/* @__PURE__ */ jsx116("span", { className: "truncate text-sm", children: recordName(row.document, titleKey) }),
|
|
35412
34965
|
/* @__PURE__ */ jsx116("span", { className: "truncate text-xs text-muted-foreground", "data-testid": "archived-who", children: archivedByLine(row) }),
|
|
35413
|
-
|
|
34966
|
+
refusal3 && refusal3.recordId === row.id ? /* @__PURE__ */ jsx116(RefusalNotice, { error: refusal3.error, className: "mt-2" }) : null
|
|
35414
34967
|
] }),
|
|
35415
34968
|
mayRestore ? /* @__PURE__ */ jsx116(
|
|
35416
34969
|
Button71,
|
|
@@ -35439,7 +34992,7 @@ function RetiredColumns({ tableId, mayRestore, whyNot }) {
|
|
|
35439
34992
|
const [rows, setRows] = useState94(null);
|
|
35440
34993
|
const [error, setError] = useState94(null);
|
|
35441
34994
|
const [restoring, setRestoring] = useState94(null);
|
|
35442
|
-
const [
|
|
34995
|
+
const [refusal3, setRefusal] = useState94(null);
|
|
35443
34996
|
const read = useCallback40(async () => {
|
|
35444
34997
|
const answer = await client.fieldsRetired({ table_id: tableId });
|
|
35445
34998
|
if (answer.ok) {
|
|
@@ -35483,7 +35036,7 @@ function RetiredColumns({ tableId, mayRestore, whyNot }) {
|
|
|
35483
35036
|
/* @__PURE__ */ jsxs106("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
35484
35037
|
/* @__PURE__ */ jsx116("span", { className: "truncate text-sm", children: name }),
|
|
35485
35038
|
/* @__PURE__ */ jsx116("span", { className: "truncate text-xs text-muted-foreground", children: retiredColumnLine(row) }),
|
|
35486
|
-
|
|
35039
|
+
refusal3 && refusal3.fieldId === row.id ? /* @__PURE__ */ jsx116(RefusalNotice, { error: refusal3.error, className: "mt-2" }) : null
|
|
35487
35040
|
] }),
|
|
35488
35041
|
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
35042
|
]
|
|
@@ -35552,7 +35105,7 @@ function ArchivedPortals({
|
|
|
35552
35105
|
const [confirming, setConfirming] = useState95(null);
|
|
35553
35106
|
const [typed2, setTyped] = useState95("");
|
|
35554
35107
|
const [restoring, setRestoring] = useState95(null);
|
|
35555
|
-
const [
|
|
35108
|
+
const [refusal3, setRefusal] = useState95(null);
|
|
35556
35109
|
const [said2, setSaid] = useState95(null);
|
|
35557
35110
|
const read = useCallback41(async () => {
|
|
35558
35111
|
const answered = await client.listPortals({ archived: "archived" });
|
|
@@ -35668,7 +35221,7 @@ function ArchivedPortals({
|
|
|
35668
35221
|
)
|
|
35669
35222
|
] })
|
|
35670
35223
|
] }) : null,
|
|
35671
|
-
|
|
35224
|
+
refusal3 && refusal3.portalId === portal.portal_id ? /* @__PURE__ */ jsx117(RefusalNotice, { error: refusal3.error }) : null
|
|
35672
35225
|
]
|
|
35673
35226
|
},
|
|
35674
35227
|
portal.portal_id
|
|
@@ -35702,10 +35255,10 @@ import { useTable as useTable20 } from "@ai-matrx/records/react";
|
|
|
35702
35255
|
var NOOP3 = () => {
|
|
35703
35256
|
};
|
|
35704
35257
|
function viewActions(whyNot, host) {
|
|
35705
|
-
const one = (
|
|
35706
|
-
if (whyNot !== null) return { ...
|
|
35707
|
-
if (!run) return { ...
|
|
35708
|
-
return { ...
|
|
35258
|
+
const one = (base2, run) => {
|
|
35259
|
+
if (whyNot !== null) return { ...base2, disabledReason: whyNot, run: NOOP3 };
|
|
35260
|
+
if (!run) return { ...base2, disabledReason: ACTION_NOT_HERE_REASON, run: NOOP3 };
|
|
35261
|
+
return { ...base2, run };
|
|
35709
35262
|
};
|
|
35710
35263
|
return [
|
|
35711
35264
|
one({ id: "rename", label: "Rename view\u2026", icon: "pencil", group: "organize", verb: "rename" }, host.rename),
|
|
@@ -35717,8 +35270,8 @@ function viewActions(whyNot, host) {
|
|
|
35717
35270
|
];
|
|
35718
35271
|
}
|
|
35719
35272
|
function copyName(name, taken) {
|
|
35720
|
-
const
|
|
35721
|
-
if (!taken.includes(
|
|
35273
|
+
const base2 = `${name} (copy)`;
|
|
35274
|
+
if (!taken.includes(base2)) return base2;
|
|
35722
35275
|
for (let n = 2; ; n += 1) {
|
|
35723
35276
|
const next = `${name} (copy ${n})`;
|
|
35724
35277
|
if (!taken.includes(next)) return next;
|
|
@@ -36490,7 +36043,7 @@ function MyChecklistSteps({
|
|
|
36490
36043
|
}, [held, onSteps]);
|
|
36491
36044
|
const steps = onlyIds ? held.filter((s) => onlyIds.has(s.step_id)) : held;
|
|
36492
36045
|
const [busy, setBusy] = useState98(null);
|
|
36493
|
-
const [
|
|
36046
|
+
const [refusal3, setRefusal] = useState98(null);
|
|
36494
36047
|
const complete = useCallback44(
|
|
36495
36048
|
async (step2, evidence) => {
|
|
36496
36049
|
setBusy(step2.step_id);
|
|
@@ -36513,7 +36066,7 @@ function MyChecklistSteps({
|
|
|
36513
36066
|
/* @__PURE__ */ jsx120("span", { className: "tabular-nums", children: steps.length })
|
|
36514
36067
|
] }),
|
|
36515
36068
|
error ? /* @__PURE__ */ jsx120(RefusalNotice, { error }) : null,
|
|
36516
|
-
|
|
36069
|
+
refusal3 ? /* @__PURE__ */ jsx120(RefusalNotice, { error: refusal3 }) : null,
|
|
36517
36070
|
/* @__PURE__ */ jsx120("ol", { className: "flex flex-col gap-1.5", children: steps.map(
|
|
36518
36071
|
(step2) => actions ? /* @__PURE__ */ jsxs110("div", { className: "flex flex-col gap-0.5", "data-step-row": step2.step_id, children: [
|
|
36519
36072
|
/* @__PURE__ */ jsx120(StepRow, { step: step2, busy: busy === step2.step_id, onComplete: (evidence) => void complete(step2, evidence) }),
|
|
@@ -36713,7 +36266,7 @@ function ChecklistTemplateEditor({
|
|
|
36713
36266
|
const [saved, setSaved] = useState98(false);
|
|
36714
36267
|
const [name, setName] = useState98("");
|
|
36715
36268
|
const [rows, setRows] = useState98([{ ...EMPTY_ROW }]);
|
|
36716
|
-
const [
|
|
36269
|
+
const [refusal3, setRefusal] = useState98(null);
|
|
36717
36270
|
const [error, setError] = useState98(null);
|
|
36718
36271
|
const [busy, setBusy] = useState98(false);
|
|
36719
36272
|
const [loading, setLoading] = useState98(Boolean(templateId));
|
|
@@ -36889,10 +36442,10 @@ function ChecklistTemplateEditor({
|
|
|
36889
36442
|
] }, index)) }),
|
|
36890
36443
|
/* @__PURE__ */ jsxs110("div", { className: "flex items-center gap-1.5", children: [
|
|
36891
36444
|
/* @__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 ||
|
|
36445
|
+
/* @__PURE__ */ jsx120(Button75, { size: "sm", disabled: busy || refusal3 !== null || spec.steps.length === 0, onClick: () => void save(), children: busy ? "\u2026" : "Save" }),
|
|
36893
36446
|
saved && !busy ? /* @__PURE__ */ jsx120("span", { className: "text-xs text-muted-foreground", "data-testid": "checklist-editor-saved", role: "status", children: "Saved" }) : null
|
|
36894
36447
|
] }),
|
|
36895
|
-
|
|
36448
|
+
refusal3 ? /* @__PURE__ */ jsx120("p", { className: "text-xs text-muted-foreground", "data-testid": "checklist-editor-refusal", children: refusal3 }) : null
|
|
36896
36449
|
] });
|
|
36897
36450
|
}
|
|
36898
36451
|
function toStepSpec(row, index) {
|
|
@@ -42228,7 +41781,7 @@ function FormStage({
|
|
|
42228
41781
|
const [answers, setAnswers] = useState114(() => ({ ...initialAnswers ?? {} }));
|
|
42229
41782
|
const [at, setAt] = useState114(0);
|
|
42230
41783
|
const [error, setError] = useState114(null);
|
|
42231
|
-
const [
|
|
41784
|
+
const [refusal3, setRefusal] = useState114(null);
|
|
42232
41785
|
const [writing, setWriting] = useState114(false);
|
|
42233
41786
|
const [done, setDone] = useState114(null);
|
|
42234
41787
|
const [hidden, setHidden] = useState114({});
|
|
@@ -42601,10 +42154,10 @@ function FormStage({
|
|
|
42601
42154
|
) : null,
|
|
42602
42155
|
form.intro && index === 0 ? /* @__PURE__ */ jsx137("p", { className: "text-base text-muted-foreground", children: authored(host, form.intro, "form-intro") }) : null,
|
|
42603
42156
|
error ? /* @__PURE__ */ jsx137(RefusalNotice, { error, className: "text-left" }) : null,
|
|
42604
|
-
|
|
42157
|
+
refusal3 ? /* @__PURE__ */ jsx137(
|
|
42605
42158
|
RefusalNotice,
|
|
42606
42159
|
{
|
|
42607
|
-
error:
|
|
42160
|
+
error: refusal3,
|
|
42608
42161
|
className: "text-left",
|
|
42609
42162
|
onKeepEditing: () => {
|
|
42610
42163
|
setRefusal(null);
|
|
@@ -42799,11 +42352,11 @@ import {
|
|
|
42799
42352
|
formLookDocument
|
|
42800
42353
|
} from "@ai-matrx/records/forms";
|
|
42801
42354
|
import { Fragment as Fragment56, jsx as jsx138, jsxs as jsxs128 } from "react/jsx-runtime";
|
|
42802
|
-
function freshFormName(
|
|
42355
|
+
function freshFormName(base2, taken) {
|
|
42803
42356
|
const names = new Set(taken.map((n) => n.trim().toLowerCase()));
|
|
42804
|
-
if (!names.has(
|
|
42357
|
+
if (!names.has(base2.toLowerCase())) return base2;
|
|
42805
42358
|
for (let n = 2; ; n += 1) {
|
|
42806
|
-
const next = `${
|
|
42359
|
+
const next = `${base2} ${n}`;
|
|
42807
42360
|
if (!names.has(next.toLowerCase())) return next;
|
|
42808
42361
|
}
|
|
42809
42362
|
}
|
|
@@ -43100,8 +42653,8 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, startWithOne,
|
|
|
43100
42653
|
return;
|
|
43101
42654
|
}
|
|
43102
42655
|
setMakeOnMount("making");
|
|
43103
|
-
const
|
|
43104
|
-
void create(freshFormName(
|
|
42656
|
+
const base2 = table.data?.name?.trim() ? `${table.data.name.trim()} form` : "Form";
|
|
42657
|
+
void create(freshFormName(base2, forms.map((f) => f.name))).then(
|
|
43105
42658
|
(made) => setMakeOnMount(made ? "made" : "not-made")
|
|
43106
42659
|
);
|
|
43107
42660
|
}, [createOnMount, makeOnMount, forms, fields.data, create, table.data, table.error]);
|
|
@@ -45063,7 +44616,7 @@ function AddChart({ subject, onAdd, onClose }) {
|
|
|
45063
44616
|
const field2 = all.find((f) => f.key === key);
|
|
45064
44617
|
return field2 ? scalarText(field2, value, labels) : String(value);
|
|
45065
44618
|
};
|
|
45066
|
-
const [
|
|
44619
|
+
const [measureKey4, setMeasureKey] = useState121("count");
|
|
45067
44620
|
const [splitKey, setSplitKey] = useState121("none");
|
|
45068
44621
|
const [kind, setKind] = useState121("auto");
|
|
45069
44622
|
const [filter, setFilter] = useState121({});
|
|
@@ -45071,7 +44624,7 @@ function AddChart({ subject, onAdd, onClose }) {
|
|
|
45071
44624
|
const numbers = numberColumns(all);
|
|
45072
44625
|
const choices = offerableFields(all, "choice");
|
|
45073
44626
|
const dates = offerableFields(all, "date");
|
|
45074
|
-
const measure =
|
|
44627
|
+
const measure = measureKey4 === "count" ? { op: "count" } : { op: measureKey4.split(":")[0], key: measureKey4.split(":")[1] };
|
|
45075
44628
|
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
44629
|
const shape = kind !== "auto" ? kind : split.kind === "period" ? "line" : split.kind === "column" ? "column" : "number";
|
|
45077
44630
|
function pickTable(next) {
|
|
@@ -45089,7 +44642,7 @@ function AddChart({ subject, onAdd, onClose }) {
|
|
|
45089
44642
|
return /* @__PURE__ */ jsxs135("div", { className: "flex flex-col gap-2 rounded border p-2 text-xs", role: "group", "aria-label": "Add chart", children: [
|
|
45090
44643
|
/* @__PURE__ */ jsxs135("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
45091
44644
|
/* @__PURE__ */ jsx146("div", { className: "min-w-[12rem]", children: /* @__PURE__ */ jsx146(TablePicker, { dataSource: client.config.dataSource, value: tableId, onChange: pickTable }) }),
|
|
45092
|
-
/* @__PURE__ */ jsxs135(Select17, { value:
|
|
44645
|
+
/* @__PURE__ */ jsxs135(Select17, { value: measureKey4, onValueChange: setMeasureKey, children: [
|
|
45093
44646
|
/* @__PURE__ */ jsx146(SelectTrigger17, { size: "sm", "aria-label": "What the chart counts", className: "h-7 min-w-[8rem] text-xs", children: /* @__PURE__ */ jsx146(SelectValue17, {}) }),
|
|
45094
44647
|
/* @__PURE__ */ jsxs135(SelectContent17, { children: [
|
|
45095
44648
|
/* @__PURE__ */ jsx146(SelectItem17, { value: "count", children: "How many" }),
|
|
@@ -45185,14 +44738,14 @@ function filterTargets(filter, blocks) {
|
|
|
45185
44738
|
if (filter.targets && filter.targets.length > 0) return filter.targets;
|
|
45186
44739
|
return blocks.filter((b) => b.kind === "list" && b.table_id === filter.table_id).map((b) => b.id);
|
|
45187
44740
|
}
|
|
45188
|
-
function combineFilter(
|
|
44741
|
+
function combineFilter(base2, extra, fieldIdOf) {
|
|
45189
44742
|
const extraKeys = Object.keys(extra);
|
|
45190
|
-
if (!
|
|
44743
|
+
if (!base2 || !isRuleFilter3(base2) && Object.keys(base2).length === 0) {
|
|
45191
44744
|
return { filter: extraKeys.length > 0 ? { ...extra } : null, dropped: [] };
|
|
45192
44745
|
}
|
|
45193
|
-
if (!isRuleFilter3(
|
|
44746
|
+
if (!isRuleFilter3(base2)) return { filter: { ...base2, ...extra }, dropped: [] };
|
|
45194
44747
|
const dropped = [];
|
|
45195
|
-
let rule =
|
|
44748
|
+
let rule = base2;
|
|
45196
44749
|
for (const key of extraKeys) {
|
|
45197
44750
|
const id = fieldIdOf(key);
|
|
45198
44751
|
if (!id) {
|
|
@@ -45848,372 +45401,9 @@ import { Badge as Badge24, BasicInput as BasicInput33, Button as Button97, Check
|
|
|
45848
45401
|
import { useFields as useFields31, useRecordsClient as useRecordsClient88 } from "@ai-matrx/records/react";
|
|
45849
45402
|
|
|
45850
45403
|
// 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
|
-
}
|
|
45404
|
+
var question_exports = {};
|
|
45405
|
+
__reExport(question_exports, questions_star);
|
|
45406
|
+
import * as questions_star from "@ai-matrx/records/questions";
|
|
46217
45407
|
|
|
46218
45408
|
// src/QuestionPanel.tsx
|
|
46219
45409
|
import { Fragment as Fragment59, jsx as jsx148, jsxs as jsxs137 } from "react/jsx-runtime";
|
|
@@ -46269,12 +45459,12 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46269
45459
|
}
|
|
46270
45460
|
let live = true;
|
|
46271
45461
|
void (async () => {
|
|
46272
|
-
const mine2 = await unreadableKeys(client, tableId, all);
|
|
45462
|
+
const mine2 = await (0, question_exports.unreadableKeys)(client, tableId, all);
|
|
46273
45463
|
const out = {};
|
|
46274
45464
|
for (const rel of all.filter((f) => editorKindFor(f) === "relation" && f.relation_target && !mine2.has(f.key))) {
|
|
46275
45465
|
const target = await client.fields({ table_id: rel.relation_target });
|
|
46276
45466
|
if (!target.ok) continue;
|
|
46277
|
-
const theirs = await unreadableKeys(client, rel.relation_target, target.data);
|
|
45467
|
+
const theirs = await (0, question_exports.unreadableKeys)(client, rel.relation_target, target.data);
|
|
46278
45468
|
out[rel.key] = { relation: rel, fields: target.data.filter((f) => !theirs.has(f.key) && editorKindFor(f) !== "relation") };
|
|
46279
45469
|
}
|
|
46280
45470
|
if (!live) return;
|
|
@@ -46289,7 +45479,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46289
45479
|
const [saved, setSaved] = useState123(null);
|
|
46290
45480
|
const [savedEpoch, setSavedEpoch] = useState123(0);
|
|
46291
45481
|
const [current, setCurrent] = useState123(null);
|
|
46292
|
-
const [spec, setSpec] = useState123(newQuestion);
|
|
45482
|
+
const [spec, setSpec] = useState123(question_exports.newQuestion);
|
|
46293
45483
|
const [name, setName] = useState123("");
|
|
46294
45484
|
const [shared, setShared] = useState123(true);
|
|
46295
45485
|
const [saveError, setSaveError] = useState123(null);
|
|
@@ -46298,7 +45488,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46298
45488
|
const openedFromLink = useRef59(false);
|
|
46299
45489
|
useEffect107(() => {
|
|
46300
45490
|
let live = true;
|
|
46301
|
-
void questionsOf(client, tableId).then((answer2) => {
|
|
45491
|
+
void (0, question_exports.questionsOf)(client, tableId).then((answer2) => {
|
|
46302
45492
|
if (!live) return;
|
|
46303
45493
|
setSaved(answer2.ok ? answer2.data : []);
|
|
46304
45494
|
if (answer2.ok && activeQuestionId && !openedFromLink.current) {
|
|
@@ -46314,7 +45504,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46314
45504
|
}, [client, tableId, savedEpoch, activeQuestionId]);
|
|
46315
45505
|
const open = (q) => {
|
|
46316
45506
|
setCurrent(q);
|
|
46317
|
-
setSpec(q ? q.spec : newQuestion());
|
|
45507
|
+
setSpec(q ? q.spec : (0, question_exports.newQuestion)());
|
|
46318
45508
|
setName(q ? q.name : "");
|
|
46319
45509
|
setShared(q ? q.shared : true);
|
|
46320
45510
|
setSaveError(null);
|
|
@@ -46333,7 +45523,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46333
45523
|
let live = true;
|
|
46334
45524
|
setAsking(true);
|
|
46335
45525
|
const t = setTimeout(() => {
|
|
46336
|
-
void askQuestion(client, tableId, spec, all).then((a) => {
|
|
45526
|
+
void (0, question_exports.askQuestion)(client, tableId, spec, all).then((a) => {
|
|
46337
45527
|
if (!live) return;
|
|
46338
45528
|
setAnswer(a);
|
|
46339
45529
|
setAsking(false);
|
|
@@ -46349,7 +45539,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46349
45539
|
setSaving(true);
|
|
46350
45540
|
setSaveError(null);
|
|
46351
45541
|
const editing = !asNew && current && mine;
|
|
46352
|
-
const kept = await questionSave(client, {
|
|
45542
|
+
const kept = await (0, question_exports.questionSave)(client, {
|
|
46353
45543
|
...editing ? { id: current.id, expectedVersion: current.version } : {},
|
|
46354
45544
|
tableId,
|
|
46355
45545
|
name: asNew && current && name.trim() === current.name ? `${name.trim()} (copy)` : name,
|
|
@@ -46367,7 +45557,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
|
|
|
46367
45557
|
};
|
|
46368
45558
|
const archive = async () => {
|
|
46369
45559
|
if (!current) return;
|
|
46370
|
-
const gone = await questionArchive(client, current.id, current.version);
|
|
45560
|
+
const gone = await (0, question_exports.questionArchive)(client, current.id, current.version);
|
|
46371
45561
|
if (!gone.ok) return setSaveError(gone.error);
|
|
46372
45562
|
open(null);
|
|
46373
45563
|
setSavedEpoch((n) => n + 1);
|
|
@@ -46522,17 +45712,17 @@ function Measures({ measures, fields, onChange }) {
|
|
|
46522
45712
|
const set = (i, next) => onChange(measures.map((m, j) => j === i ? next : m));
|
|
46523
45713
|
return /* @__PURE__ */ jsxs137("div", { className: "flex flex-col gap-1", children: [
|
|
46524
45714
|
measures.map((m, i) => {
|
|
46525
|
-
const eligible = measurableFields(fields, m.op);
|
|
45715
|
+
const eligible = (0, question_exports.measurableFields)(fields, m.op);
|
|
46526
45716
|
return /* @__PURE__ */ jsxs137("div", { className: "flex items-center gap-1", "data-testid": "question-measure", children: [
|
|
46527
45717
|
/* @__PURE__ */ jsx148(
|
|
46528
45718
|
PickOne,
|
|
46529
45719
|
{
|
|
46530
45720
|
label: "Measure",
|
|
46531
45721
|
value: m.op,
|
|
46532
|
-
options: QUESTION_OPS.map((op2) => ({ value: op2, label: OP_LABEL[op2] })),
|
|
45722
|
+
options: question_exports.QUESTION_OPS.map((op2) => ({ value: op2, label: OP_LABEL[op2] })),
|
|
46533
45723
|
onChange: (op2) => {
|
|
46534
45724
|
const nextOp = op2;
|
|
46535
|
-
const keep = nextOp !== "count" && measurableFields(fields, nextOp).some((f) => f.key === m.key);
|
|
45725
|
+
const keep = nextOp !== "count" && (0, question_exports.measurableFields)(fields, nextOp).some((f) => f.key === m.key);
|
|
46536
45726
|
set(i, nextOp === "count" ? { op: "count" } : { op: nextOp, ...keep ? { key: m.key } : {} });
|
|
46537
45727
|
},
|
|
46538
45728
|
className: "w-28",
|
|
@@ -46964,14 +46154,14 @@ function questionFromWords(text, fields, choices = {}) {
|
|
|
46964
46154
|
const measured = head === "" ? null : columnNamed2(head, names);
|
|
46965
46155
|
if (op2 === null) {
|
|
46966
46156
|
if (head === "") op2 = "count";
|
|
46967
|
-
else if (measured && measurableFields([...fields], "sum").some((f) => f.key === measured.key)) op2 = "sum";
|
|
46157
|
+
else if (measured && (0, question_exports.measurableFields)([...fields], "sum").some((f) => f.key === measured.key)) op2 = "sum";
|
|
46968
46158
|
else return { ok: false, why: "Start with count, sum, average, smallest or largest" };
|
|
46969
46159
|
}
|
|
46970
|
-
const spec = { ...newQuestion(), group };
|
|
46160
|
+
const spec = { ...(0, question_exports.newQuestion)(), group };
|
|
46971
46161
|
let measureReads = "Count";
|
|
46972
46162
|
if (op2 !== "count") {
|
|
46973
46163
|
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)) {
|
|
46164
|
+
if (!(0, question_exports.measurableFields)([...fields], op2).some((f) => f.key === measured.key)) {
|
|
46975
46165
|
return { ok: false, why: `${fieldName(measured)} is not a number column` };
|
|
46976
46166
|
}
|
|
46977
46167
|
spec.measures = [{ op: op2, key: measured.key }];
|
|
@@ -47008,7 +46198,7 @@ function TableAsk({ tableId, onOpenInQuestions }) {
|
|
|
47008
46198
|
const read = questionFromWords(words2, all, choices);
|
|
47009
46199
|
if (!read.ok) return setSaid({ kind: "not-read", why: read.why });
|
|
47010
46200
|
setSaid({ kind: "asking", reads: read.reads });
|
|
47011
|
-
const answered = await askQuestion(client, tableId, read.spec, all);
|
|
46201
|
+
const answered = await (0, question_exports.askQuestion)(client, tableId, read.spec, all);
|
|
47012
46202
|
setSaid(answered.ok ? { kind: "answer", reads: read.reads, spec: read.spec, answer: answered.data } : { kind: "refused", error: answered.error });
|
|
47013
46203
|
};
|
|
47014
46204
|
return /* @__PURE__ */ jsxs138(Popover14, { open, onOpenChange: setOpen, children: [
|
|
@@ -49608,16 +48798,16 @@ function toolbarFold(input) {
|
|
|
49608
48798
|
};
|
|
49609
48799
|
const withGap = (width) => width > 0 ? width + gap : 0;
|
|
49610
48800
|
const shareNow = input.share ? withGap(input.share.now) : 0;
|
|
49611
|
-
const
|
|
48801
|
+
const base2 = pieces.reduce((rest, p) => rest - withGap(p.piece.now), needsNow - shareNow);
|
|
49612
48802
|
const stages = input.tools ? [0, 1, 2, 3] : [0, 1, 2];
|
|
49613
48803
|
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)),
|
|
48804
|
+
const needs = stages.map((fold) => pieces.reduce((sum, p) => sum + withGap(widthAt(p, fold)), base2 + shareOn));
|
|
49615
48805
|
const fits = needs.findIndex((need) => need <= available + 0.5);
|
|
49616
48806
|
if (fits >= 0) return stages[fits];
|
|
49617
48807
|
const least = Math.min(...needs);
|
|
49618
48808
|
const most = stages[needs.findIndex((need) => need <= least + 0.5)];
|
|
49619
48809
|
if (!input.tools || !input.share) return most;
|
|
49620
|
-
const fixed = pieces.reduce((sum, p) => sum + withGap(p.stage === 3 ? SLOT_MIN : widthAt(p, 3)),
|
|
48810
|
+
const fixed = pieces.reduce((sum, p) => sum + withGap(p.stage === 3 ? SLOT_MIN : widthAt(p, 3)), base2 + shareOn);
|
|
49621
48811
|
return fixed > available + 0.5 ? 4 : most;
|
|
49622
48812
|
}
|
|
49623
48813
|
function naturalWidth(el) {
|
|
@@ -49774,7 +48964,7 @@ function useSlotScroll(slot) {
|
|
|
49774
48964
|
}
|
|
49775
48965
|
|
|
49776
48966
|
// src/TablePage.tsx
|
|
49777
|
-
import { isUuidShape as
|
|
48967
|
+
import { isUuidShape as isUuidShape3 } from "@ai-matrx/kit/uuid";
|
|
49778
48968
|
import { Fragment as Fragment68, jsx as jsx163, jsxs as jsxs152 } from "react/jsx-runtime";
|
|
49779
48969
|
var RAIL_TITLE = {
|
|
49780
48970
|
settings: "Table settings",
|
|
@@ -49861,7 +49051,7 @@ function TableNotHere({
|
|
|
49861
49051
|
const client = useRecordsClient98();
|
|
49862
49052
|
const [archived, setArchived] = useState138({ phase: "asking" });
|
|
49863
49053
|
const [restoring, setRestoring] = useState138(false);
|
|
49864
|
-
const [
|
|
49054
|
+
const [refusal3, setRefusal] = useState138(null);
|
|
49865
49055
|
useEffect117(() => {
|
|
49866
49056
|
let alive = true;
|
|
49867
49057
|
void client.tableArchived({ table_id: tableId }).then((answered) => {
|
|
@@ -49879,7 +49069,7 @@ function TableNotHere({
|
|
|
49879
49069
|
/* @__PURE__ */ jsx163("p", { className: "text-sm font-medium", children: "This table is archived" }),
|
|
49880
49070
|
/* @__PURE__ */ jsx163("p", { className: "max-w-prose text-xs text-muted-foreground", children: TABLE_IS_ARCHIVED }),
|
|
49881
49071
|
/* @__PURE__ */ jsx163("p", { className: "text-xs text-muted-foreground", children: archivedByLine2(row) }),
|
|
49882
|
-
|
|
49072
|
+
refusal3 ? /* @__PURE__ */ jsx163(RefusalNotice, { error: refusal3 }) : null,
|
|
49883
49073
|
/* @__PURE__ */ jsxs152("div", { className: "flex gap-2", children: [
|
|
49884
49074
|
/* @__PURE__ */ jsx163(
|
|
49885
49075
|
Button110,
|
|
@@ -49996,7 +49186,7 @@ function openingView(activeView, activeDashboardId) {
|
|
|
49996
49186
|
}
|
|
49997
49187
|
function savedViewFromParam(activeView) {
|
|
49998
49188
|
const word = typeof activeView === "string" ? activeView.trim() : "";
|
|
49999
|
-
return
|
|
49189
|
+
return isUuidShape3(word) ? word.toLowerCase() : null;
|
|
50000
49190
|
}
|
|
50001
49191
|
function addressForView(view, layout) {
|
|
50002
49192
|
return view && !view.isDefault ? view.id : layout;
|
|
@@ -50368,7 +49558,7 @@ function TablePage({
|
|
|
50368
49558
|
const [designateRefused, setDesignateRefused] = useState138(null);
|
|
50369
49559
|
const opensAs = view?.isDefault ? view.layout : null;
|
|
50370
49560
|
const canDesignate = Boolean(
|
|
50371
|
-
rights.organise && view && layoutShowing && layoutShowing !== opensAs &&
|
|
49561
|
+
rights.organise && view && layoutShowing && layoutShowing !== opensAs && storeKeepsLayout2(layoutShowing)
|
|
50372
49562
|
);
|
|
50373
49563
|
const layoutShowingLabel = layoutShowing ? LAYOUT_LABEL[layoutShowing] : "";
|
|
50374
49564
|
const designate = async () => {
|
|
@@ -50872,7 +50062,7 @@ function TablePage({
|
|
|
50872
50062
|
QuestionPanel,
|
|
50873
50063
|
{
|
|
50874
50064
|
tableId,
|
|
50875
|
-
activeQuestionId: questionsFromLink && activeItemId &&
|
|
50065
|
+
activeQuestionId: questionsFromLink && activeItemId && isUuidShape3(activeItemId) ? activeItemId : null,
|
|
50876
50066
|
draft: questionDraft
|
|
50877
50067
|
}
|
|
50878
50068
|
) : main === "archived" ? (
|
|
@@ -51128,7 +50318,7 @@ function EntityBoard({ entity, groupBy, cardFields, onOpenRecord, className }) {
|
|
|
51128
50318
|
const writable = !column.readOnly && entity.canUpdate;
|
|
51129
50319
|
const placed = (row) => entityValueText(column, entityCellValue(row, column)) || null;
|
|
51130
50320
|
const lanes = [...words2.map((w) => ({ key: w, label: w })), { key: "", label: `No ${column.label.toLowerCase()}` }];
|
|
51131
|
-
const
|
|
50321
|
+
const rowsOf2 = (key) => entity.rows.filter((r) => (placed(r) ?? "") === key);
|
|
51132
50322
|
const drop = async (event, to) => {
|
|
51133
50323
|
event.preventDefault();
|
|
51134
50324
|
setOver(null);
|
|
@@ -51140,7 +50330,7 @@ function EntityBoard({ entity, groupBy, cardFields, onOpenRecord, className }) {
|
|
|
51140
50330
|
if (says) setRefused({ to, says });
|
|
51141
50331
|
};
|
|
51142
50332
|
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 =
|
|
50333
|
+
const cards = rowsOf2(lane.key);
|
|
51144
50334
|
if (lane.key === "" && cards.length === 0) return null;
|
|
51145
50335
|
return /* @__PURE__ */ jsxs153(
|
|
51146
50336
|
"section",
|
|
@@ -51182,9 +50372,9 @@ function EntityBoard({ entity, groupBy, cardFields, onOpenRecord, className }) {
|
|
|
51182
50372
|
);
|
|
51183
50373
|
}) });
|
|
51184
50374
|
}
|
|
51185
|
-
function blockOfAnswer(answer,
|
|
50375
|
+
function blockOfAnswer(answer, base2, by) {
|
|
51186
50376
|
if (!answer.ok) {
|
|
51187
|
-
return { ...
|
|
50377
|
+
return { ...base2, refused: refusalSentence(answer.error) || "This chart could not be read.", ...answer.error.code ? { sqlstate: answer.error.code } : {} };
|
|
51188
50378
|
}
|
|
51189
50379
|
const rows = answer.data.rows.filter((r) => by ? r.kind !== "total" : r.kind === "total").map((r) => {
|
|
51190
50380
|
const groups = {};
|
|
@@ -51196,7 +50386,7 @@ function blockOfAnswer(answer, base, by) {
|
|
|
51196
50386
|
for (const [k, v] of Object.entries(r.measures ?? {})) measuresOut[k] = typeof v === "number" ? v : v === null ? null : Number(v);
|
|
51197
50387
|
return { groups, measures: measuresOut, row_count: Number(r.row_count) };
|
|
51198
50388
|
});
|
|
51199
|
-
return { ...
|
|
50389
|
+
return { ...base2, rows };
|
|
51200
50390
|
}
|
|
51201
50391
|
function EntityChartBlock({ source, kind, by, measure, title, where, organization, centerValue, variant, className }) {
|
|
51202
50392
|
const client = useRecordsClient99();
|
|
@@ -51204,9 +50394,9 @@ function EntityChartBlock({ source, kind, by, measure, title, where, organizatio
|
|
|
51204
50394
|
const ask = JSON.stringify([source.token, by ?? null, m, where ?? null, organization ?? null]);
|
|
51205
50395
|
const question = entityChartQuestion({ by, measure, where, organization });
|
|
51206
50396
|
const measures = [m.op === "count" ? { op: "count" } : { op: m.op, key: m.of }];
|
|
51207
|
-
const
|
|
50397
|
+
const base2 = { title: title ?? "", kind, measures, group_by: by ? [by] : [] };
|
|
51208
50398
|
const seeded = useSeededAnswerAt(`entity-chart:${ask}`, (c) => c.drillAsk({ source, question }));
|
|
51209
|
-
const [block, setBlock] = useState139(() => seeded ? blockOfAnswer({ ok: true, data: seeded.data },
|
|
50399
|
+
const [block, setBlock] = useState139(() => seeded ? blockOfAnswer({ ok: true, data: seeded.data }, base2, by) : null);
|
|
51210
50400
|
const seededFor = useRef63(seeded ? { ask: `${ask}|${kind}|${title ?? ""}`, at: seeded.at } : null);
|
|
51211
50401
|
useEffect118(() => {
|
|
51212
50402
|
const held = seededFor.current;
|
|
@@ -51215,7 +50405,7 @@ function EntityChartBlock({ source, kind, by, measure, title, where, organizatio
|
|
|
51215
50405
|
let cancelled = false;
|
|
51216
50406
|
void client.drillAsk({ source, question }).then((answer) => {
|
|
51217
50407
|
if (cancelled) return;
|
|
51218
|
-
setBlock(blockOfAnswer(answer,
|
|
50408
|
+
setBlock(blockOfAnswer(answer, base2, by));
|
|
51219
50409
|
});
|
|
51220
50410
|
return () => {
|
|
51221
50411
|
cancelled = true;
|
|
@@ -51493,7 +50683,7 @@ function BindingDetails({
|
|
|
51493
50683
|
}, [disabled, shape, binding, fields.loading, fieldList, table.data, onChange]);
|
|
51494
50684
|
const selectShape = (next) => {
|
|
51495
50685
|
if (next === shape) return;
|
|
51496
|
-
const
|
|
50686
|
+
const base2 = {
|
|
51497
50687
|
kind: "merge_field",
|
|
51498
50688
|
source: "record",
|
|
51499
50689
|
semantic_type: next,
|
|
@@ -51501,21 +50691,21 @@ function BindingDetails({
|
|
|
51501
50691
|
missing: binding.missing,
|
|
51502
50692
|
override_policy: "shown_locked"
|
|
51503
50693
|
};
|
|
51504
|
-
if (next !== "collection" && binding.record_id)
|
|
51505
|
-
if (next === "value" && binding.field_key)
|
|
50694
|
+
if (next !== "collection" && binding.record_id) base2.record_id = binding.record_id;
|
|
50695
|
+
if (next === "value" && binding.field_key) base2.field_key = binding.field_key;
|
|
51506
50696
|
if (next === "collection") {
|
|
51507
50697
|
const limit = binding.limit ?? defaultRowLimit;
|
|
51508
|
-
if (limit)
|
|
50698
|
+
if (limit) base2.limit = limit;
|
|
51509
50699
|
}
|
|
51510
50700
|
if (next !== "value" && binding.transform) {
|
|
51511
|
-
|
|
50701
|
+
base2.transform = {
|
|
51512
50702
|
name: "list",
|
|
51513
50703
|
template: binding.transform.template,
|
|
51514
50704
|
...binding.transform.join !== void 0 ? { join: binding.transform.join } : {},
|
|
51515
|
-
...next === "collection" &&
|
|
50705
|
+
...next === "collection" && base2.limit !== void 0 ? { max: base2.limit } : {}
|
|
51516
50706
|
};
|
|
51517
50707
|
}
|
|
51518
|
-
onChange(
|
|
50708
|
+
onChange(base2);
|
|
51519
50709
|
};
|
|
51520
50710
|
const fieldOptions = fieldList.map((f) => ({ value: f.key, label: fieldName(f) }));
|
|
51521
50711
|
const template = binding.transform?.template ?? "";
|
|
@@ -51829,10 +51019,21 @@ function PreviewForms({ preview, booking }) {
|
|
|
51829
51019
|
] }, p.id)) : null
|
|
51830
51020
|
] });
|
|
51831
51021
|
}
|
|
51022
|
+
var export_QUESTION_OPS = question_exports.QUESTION_OPS;
|
|
51023
|
+
var export_QUESTION_SURFACE = question_exports.QUESTION_SURFACE;
|
|
51832
51024
|
var export_asRefusal = refusals_exports.asRefusal;
|
|
51025
|
+
var export_askQuestion = question_exports.askQuestion;
|
|
51026
|
+
var export_flatWhere = question_exports.flatWhere;
|
|
51027
|
+
var export_measurableFields = question_exports.measurableFields;
|
|
51028
|
+
var export_newQuestion = question_exports.newQuestion;
|
|
51029
|
+
var export_questionArchive = question_exports.questionArchive;
|
|
51030
|
+
var export_questionFromDefinition = question_exports.questionFromDefinition;
|
|
51031
|
+
var export_questionSave = question_exports.questionSave;
|
|
51032
|
+
var export_questionsOf = question_exports.questionsOf;
|
|
51833
51033
|
var export_refusal = refusals_exports.refusal;
|
|
51834
51034
|
var export_refusalFromThrown = refusals_exports.refusalFromThrown;
|
|
51835
51035
|
var export_refusalOr = refusals_exports.refusalOr;
|
|
51036
|
+
var export_unreadableKeys = question_exports.unreadableKeys;
|
|
51836
51037
|
export {
|
|
51837
51038
|
ABSENCE_WORD_LABEL,
|
|
51838
51039
|
ABSENCE_WORD_VALUES,
|
|
@@ -52006,8 +51207,8 @@ export {
|
|
|
52006
51207
|
ProvenanceBadge,
|
|
52007
51208
|
PublicPicturePicker,
|
|
52008
51209
|
PublicViewPage,
|
|
52009
|
-
QUESTION_OPS,
|
|
52010
|
-
QUESTION_SURFACE,
|
|
51210
|
+
export_QUESTION_OPS as QUESTION_OPS,
|
|
51211
|
+
export_QUESTION_SURFACE as QUESTION_SURFACE,
|
|
52011
51212
|
QuestionAnswerView,
|
|
52012
51213
|
QuestionPanel,
|
|
52013
51214
|
RECORDS_GRID_ROW_PX,
|
|
@@ -52045,8 +51246,8 @@ export {
|
|
|
52045
51246
|
STANDARD_VERBS,
|
|
52046
51247
|
STORE_ANSWERS_THESE,
|
|
52047
51248
|
STORE_DECIDES_REASON,
|
|
52048
|
-
STORE_KEEPS_TIMELINE,
|
|
52049
|
-
STORE_KEPT_LAYOUTS,
|
|
51249
|
+
STORE_KEEPS_TIMELINE2 as STORE_KEEPS_TIMELINE,
|
|
51250
|
+
STORE_KEPT_LAYOUTS2 as STORE_KEPT_LAYOUTS,
|
|
52050
51251
|
STRIP_FEATURE_ROWS,
|
|
52051
51252
|
SUBSCRIPTION_CADENCES,
|
|
52052
51253
|
SUBSCRIPTION_CADENCE_LABEL,
|
|
@@ -52120,7 +51321,7 @@ export {
|
|
|
52120
51321
|
archivedRowLine,
|
|
52121
51322
|
export_asRefusal as asRefusal,
|
|
52122
51323
|
askExampleFor,
|
|
52123
|
-
askQuestion,
|
|
51324
|
+
export_askQuestion as askQuestion,
|
|
52124
51325
|
askableFields,
|
|
52125
51326
|
bindingPlaceholdersFor,
|
|
52126
51327
|
blockFromSpec,
|
|
@@ -52204,7 +51405,7 @@ export {
|
|
|
52204
51405
|
fieldTypeLabel,
|
|
52205
51406
|
fieldsForNewColumns,
|
|
52206
51407
|
filterTargets,
|
|
52207
|
-
flatWhere,
|
|
51408
|
+
export_flatWhere as flatWhere,
|
|
52208
51409
|
footerOf,
|
|
52209
51410
|
formDeclareArgs2 as formDeclareArgs,
|
|
52210
51411
|
formEmbedSnippet2 as formEmbedSnippet,
|
|
@@ -52263,10 +51464,10 @@ export {
|
|
|
52263
51464
|
looksLikeId,
|
|
52264
51465
|
machineIdentityIn,
|
|
52265
51466
|
mayNotRestoreLine,
|
|
52266
|
-
measurableFields,
|
|
51467
|
+
export_measurableFields as measurableFields,
|
|
52267
51468
|
memberName,
|
|
52268
51469
|
moveRecordValue,
|
|
52269
|
-
newQuestion,
|
|
51470
|
+
export_newQuestion as newQuestion,
|
|
52270
51471
|
nextInWords,
|
|
52271
51472
|
nextSummaryAt,
|
|
52272
51473
|
notAChoiceSentence,
|
|
@@ -52292,11 +51493,11 @@ export {
|
|
|
52292
51493
|
previewLine,
|
|
52293
51494
|
previewWords,
|
|
52294
51495
|
publiclyAnswerable,
|
|
52295
|
-
questionArchive,
|
|
52296
|
-
questionFromDefinition,
|
|
51496
|
+
export_questionArchive as questionArchive,
|
|
51497
|
+
export_questionFromDefinition as questionFromDefinition,
|
|
52297
51498
|
questionFromWords,
|
|
52298
|
-
questionSave,
|
|
52299
|
-
questionsOf,
|
|
51499
|
+
export_questionSave as questionSave,
|
|
51500
|
+
export_questionsOf as questionsOf,
|
|
52300
51501
|
railFromParam,
|
|
52301
51502
|
readLooks,
|
|
52302
51503
|
readTableShape,
|
|
@@ -52347,7 +51548,7 @@ export {
|
|
|
52347
51548
|
starterPageBlocks,
|
|
52348
51549
|
stepFromAgent,
|
|
52349
51550
|
storeDecidesRights,
|
|
52350
|
-
storeKeepsLayout,
|
|
51551
|
+
storeKeepsLayout2 as storeKeepsLayout,
|
|
52351
51552
|
storePublishesKind,
|
|
52352
51553
|
styleFromDecorations,
|
|
52353
51554
|
submissionStamp2 as submissionStamp,
|
|
@@ -52366,7 +51567,7 @@ export {
|
|
|
52366
51567
|
tokenFor,
|
|
52367
51568
|
unknownRailLine,
|
|
52368
51569
|
unknownViewLine,
|
|
52369
|
-
unreadableKeys,
|
|
51570
|
+
export_unreadableKeys as unreadableKeys,
|
|
52370
51571
|
useAddressDrill,
|
|
52371
51572
|
useCanShare,
|
|
52372
51573
|
useChoiceNudge,
|