@ai-matrx/records-ui 0.93.64 → 0.93.67
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 +23 -0
- package/dist/index.cjs +213 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -3
- package/dist/index.d.ts +25 -3
- package/dist/index.js +446 -291
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog — @ai-matrx/records-ui
|
|
2
2
|
|
|
3
|
+
## 0.93.67
|
|
4
|
+
|
|
5
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
|
+
`git diff npm/records-ui/v0.93.64..npm/records-ui/v0.93.67 -- apps/shared/records-ui`).
|
|
7
|
+
No source changes intended and no consumer action required.
|
|
8
|
+
|
|
9
|
+
## 0.93.66
|
|
10
|
+
### Unreleased
|
|
11
|
+
|
|
12
|
+
- **A booking page or a summary that exists can be changed** (lane HANDOVER, 2026-09-29): a booking page's card offered "Copy link" and "Close" only, and a summary's card on/off and a preview only, so nothing on the screen could move a page saved with UTC hours, or a Monday summary kept in UTC, to the owner's clock. Each card now has "Change it": the booking builder opens on that page (re-stated by its id, starting in the owner's zone when the page was kept in UTC), and `DigestScheduler` takes `existing` — its words, day, time and clock — and saves the same rule (`rule_id`), never a second. Proof: `a-booking-page-that-exists-can-be-changed.test.tsx`, `a-summary-that-exists-can-be-changed.test.tsx`, each red on the old panel.
|
|
13
|
+
|
|
14
|
+
- **A person who answers is told it was received** (lane HANDOVER, 2026-09-29): a form's thank-you page read "Saved to Form 1, with this form stamped on it" — the owner's bookkeeping — to a front-desk member and to strangers. It now says "Your answers were received." Proof: `a-person-who-answers-is-told-it-was-received.test.tsx`, red on the old runner.
|
|
15
|
+
|
|
16
|
+
- **A booking page is titled for one visit** (lane HANDOVER, 2026-09-29): a new page on Visits was titled "Book a 30-minute Visits appointment" — the table's name where one record's noun goes. New `singularNoun(table, fallback)` (exported, beside the grid's plural) reads the table's own singular in sentence case ("visit"; acronyms kept, "MRI scan"); the title is "Book a 30-minute visit". Proof: `a-booking-page-is-titled-for-one-visit.test.tsx`, red on the old builder.
|
|
17
|
+
|
|
18
|
+
- **A stranger's own page fills her own details** (lane HANDOVER, 2026-09-29): with every booking question now drawn by `FieldControl`, the browser's offer of a person's saved name, email and phone moved into the shared control — on a page nobody is signed into (no records client) only, so a signed-in grid never offers the front desk's own email into a patient's cell. The format control (`formatControl`) carries it too (`ownDetails`). A therapist's name is not her name. Proof: `a-strangers-own-page-fills-her-own-details.test.tsx`, red on the old control.
|
|
19
|
+
|
|
20
|
+
## 0.93.65
|
|
21
|
+
### Unreleased
|
|
22
|
+
|
|
23
|
+
- **A form built in one press is named for its table** (lane HANDOVER, 2026-09-28): "Build the form" on Cedar Ridge's Treatment Rooms made "Form 1", because the builder named it before its own read of the table had answered. It now waits for the table's row. Proof: `build-the-form-makes-the-form.test.tsx` second clause (the builder mounted alone, the table answering last), red on the old builder ("Form 1").
|
|
24
|
+
- **A list that is not hers is said once, with no count** (lane HANDOVER, 2026-09-28): a member who is Viewer on a table opened Notifications, and the Webhooks section printed the read door's refusal in red ("…is not by itself permission to rewrite somebody else's row"), then "none" and "No other system is told when these records change" — a count the screen never had. A 42501 read refusal that the table's rights agree with is now one sentence ("Which other systems are told about these records is for this table's admins." plus her rights), with no count and no red line. Proof: `a-list-that-is-not-hers-is-said-once.test.tsx`, red on the old panel.
|
|
25
|
+
|
|
3
26
|
## 0.93.64
|
|
4
27
|
|
|
5
28
|
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
package/dist/index.cjs
CHANGED
|
@@ -350,6 +350,7 @@ __export(src_exports, {
|
|
|
350
350
|
scalarText: () => scalarText,
|
|
351
351
|
seedIsSatisfied: () => seedIsSatisfied,
|
|
352
352
|
shareUnavailableReason: () => shareUnavailableReason,
|
|
353
|
+
singularNoun: () => singularNoun,
|
|
353
354
|
snoozeChoices: () => snoozeChoices,
|
|
354
355
|
specFromBlock: () => specFromBlock,
|
|
355
356
|
storeDecidesRights: () => storeDecidesRights,
|
|
@@ -749,6 +750,10 @@ function realPlural(table) {
|
|
|
749
750
|
}
|
|
750
751
|
return plural3;
|
|
751
752
|
}
|
|
753
|
+
function singularNoun(table, fallback = "record") {
|
|
754
|
+
const word = (table?.label_singular ?? "").trim() || (table?.name ?? "").trim() || fallback;
|
|
755
|
+
return word.split(/\s+/).map((w) => /^[A-Z][a-z'’-]*$/.test(w) ? w.toLowerCase() : w).join(" ");
|
|
756
|
+
}
|
|
752
757
|
function pluralNoun(table, fallback = "record") {
|
|
753
758
|
const real = table ? realPlural(table) : null;
|
|
754
759
|
if (real) return real;
|
|
@@ -2795,7 +2800,7 @@ function NumberInFormat({ format, value, onChange, disabled, id }) {
|
|
|
2795
2800
|
function formatControl(args) {
|
|
2796
2801
|
const def = (0, import_field_formats4.getFieldFormat)(args.format.id);
|
|
2797
2802
|
if (!def) return null;
|
|
2798
|
-
const { format, value, onChange, disabled, id, label } = args;
|
|
2803
|
+
const { format, value, onChange, disabled, id, label, ownDetails } = args;
|
|
2799
2804
|
const text = value === null || value === void 0 ? "" : String(value);
|
|
2800
2805
|
const commit = (raw) => onChange(raw === "" ? null : (0, import_field_formats4.parseFieldInput)(raw, format));
|
|
2801
2806
|
if (def.id === "rating") {
|
|
@@ -2818,7 +2823,17 @@ function formatControl(args) {
|
|
|
2818
2823
|
case "email":
|
|
2819
2824
|
case "url":
|
|
2820
2825
|
case "tel":
|
|
2821
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2826
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2827
|
+
import_design_system9.BasicInput,
|
|
2828
|
+
{
|
|
2829
|
+
id,
|
|
2830
|
+
type: def.editor,
|
|
2831
|
+
...ownDetails && def.editor !== "url" ? { autoComplete: def.editor === "email" ? "email" : "tel" } : {},
|
|
2832
|
+
value: text,
|
|
2833
|
+
disabled,
|
|
2834
|
+
onChange: (e) => commit(e.target.value)
|
|
2835
|
+
}
|
|
2836
|
+
);
|
|
2822
2837
|
case "color":
|
|
2823
2838
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "flex items-center gap-2", children: [
|
|
2824
2839
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
@@ -3072,14 +3087,19 @@ function TypedTextControl({ field: field2, value, onChange, disabled, id, onComm
|
|
|
3072
3087
|
] })
|
|
3073
3088
|
] });
|
|
3074
3089
|
}
|
|
3090
|
+
function isPersonsName(field2) {
|
|
3091
|
+
const words2 = `${field2.key} ${field2.label ?? ""}`.toLowerCase();
|
|
3092
|
+
return /(^|[\s_])(full[\s_]?)?name(\s|$)/.test(words2) && !/(therapist|doctor|physician|company|business|pet|room)/.test(words2);
|
|
3093
|
+
}
|
|
3075
3094
|
function FieldControl({ field: field2, value, onChange, disabled, id, autoOpen, onClose, onCommit, onCancel, addsChoices, initialSearch }) {
|
|
3076
3095
|
const host = useRecordsUi();
|
|
3077
3096
|
const kind = editorKindFor(field2);
|
|
3078
3097
|
const inputId = id ?? `field-${field2.key}`;
|
|
3098
|
+
const ownDetails = (0, import_react19.useOptionalRecordsClient)() === null;
|
|
3079
3099
|
if (isTypedDraft(value)) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TypedTextControl, { field: field2, value, onChange, disabled, id: inputId, onCommit, onCancel });
|
|
3080
3100
|
const format = formatForField(field2);
|
|
3081
3101
|
if (format && !FORMAT_BLIND_KINDS.has(String(kind))) {
|
|
3082
|
-
const own2 = formatControl({ format, value, onChange, disabled, id: inputId, label: fieldName(field2) });
|
|
3102
|
+
const own2 = formatControl({ format, value, onChange, disabled, id: inputId, label: fieldName(field2), ownDetails });
|
|
3083
3103
|
if (own2) return own2;
|
|
3084
3104
|
}
|
|
3085
3105
|
switch (kind) {
|
|
@@ -3140,6 +3160,7 @@ function FieldControl({ field: field2, value, onChange, disabled, id, autoOpen,
|
|
|
3140
3160
|
{
|
|
3141
3161
|
id: inputId,
|
|
3142
3162
|
type: kind === "email" ? "email" : kind === "phone" ? "tel" : "url",
|
|
3163
|
+
...ownDetails && kind !== "url" ? { autoComplete: kind === "email" ? "email" : "tel" } : {},
|
|
3143
3164
|
value: value === null || value === void 0 ? "" : String(value),
|
|
3144
3165
|
disabled,
|
|
3145
3166
|
onChange: (e) => onChange(e.target.value === "" ? null : e.target.value)
|
|
@@ -3177,6 +3198,7 @@ function FieldControl({ field: field2, value, onChange, disabled, id, autoOpen,
|
|
|
3177
3198
|
import_design_system10.BasicInput,
|
|
3178
3199
|
{
|
|
3179
3200
|
id: inputId,
|
|
3201
|
+
...ownDetails && isPersonsName(field2) ? { autoComplete: "name" } : {},
|
|
3180
3202
|
value: value === null || value === void 0 ? "" : String(value),
|
|
3181
3203
|
disabled,
|
|
3182
3204
|
onChange: (e) => onChange(e.target.value === "" ? null : e.target.value)
|
|
@@ -5583,6 +5605,22 @@ function archiveConfirmSentence(what) {
|
|
|
5583
5605
|
const subject = what.trim() || "it";
|
|
5584
5606
|
return `This archives ${subject}. It leaves this list, and you can restore it from Trash.`;
|
|
5585
5607
|
}
|
|
5608
|
+
var recordsWord = (n) => `${n.toLocaleString()} record${n === 1 ? "" : "s"}`;
|
|
5609
|
+
function tableArchiveSentence(s) {
|
|
5610
|
+
const p = s.progress;
|
|
5611
|
+
if (!p) return "Every record in it goes with it.";
|
|
5612
|
+
const done = p.total - p.remaining;
|
|
5613
|
+
const sofar = `${done.toLocaleString()} of ${recordsWord(p.total)} ${done === 1 ? "is" : "are"} put away`;
|
|
5614
|
+
if (s.running) {
|
|
5615
|
+
return `Archiving \u2014 ${done.toLocaleString()} of ${recordsWord(p.total)} put away.${s.slowedDown ? " The store is busy, so it is taking smaller passes; it will still finish." : ""}`;
|
|
5616
|
+
}
|
|
5617
|
+
if (p.in_progress && !s.failed && !(s.passesHere ?? 0)) {
|
|
5618
|
+
return `Archiving this table was started and not finished: ${sofar}. Carry on and it picks up where it stopped.`;
|
|
5619
|
+
}
|
|
5620
|
+
if (s.interrupted && s.failed) return `That pass did not finish: ${sofar} and nothing was lost. Carry on and it picks up where it stopped.`;
|
|
5621
|
+
if (s.interrupted) return `Stopped: ${sofar}. Carry on whenever you like; it picks up where it stopped.`;
|
|
5622
|
+
return `Its ${recordsWord(p.remaining)} ${p.remaining === 1 ? "goes" : "go"} with it.`;
|
|
5623
|
+
}
|
|
5586
5624
|
|
|
5587
5625
|
// src/tableDecorations.ts
|
|
5588
5626
|
var import_react27 = require("react");
|
|
@@ -16392,6 +16430,17 @@ function TableSettings({
|
|
|
16392
16430
|
const rights = useTableRights(table.data);
|
|
16393
16431
|
const shape = (0, import_react85.useFieldMutation)();
|
|
16394
16432
|
const archive = (0, import_react85.useTableArchive)(tableId);
|
|
16433
|
+
const client = (0, import_react85.useRecordsClient)();
|
|
16434
|
+
const ui = useRecordsUi();
|
|
16435
|
+
(0, import_react84.useEffect)(() => {
|
|
16436
|
+
let live = true;
|
|
16437
|
+
void archive.preview().then((answer) => {
|
|
16438
|
+
if (live && answer?.in_progress) setAskingToDelete(true);
|
|
16439
|
+
});
|
|
16440
|
+
return () => {
|
|
16441
|
+
live = false;
|
|
16442
|
+
};
|
|
16443
|
+
}, [tableId]);
|
|
16395
16444
|
const [editing, setEditing] = (0, import_react84.useState)(null);
|
|
16396
16445
|
const [askingToDelete, setAskingToDelete] = (0, import_react84.useState)(false);
|
|
16397
16446
|
const [askingToRemove, setAskingToRemove] = (0, import_react84.useState)(null);
|
|
@@ -16420,6 +16469,16 @@ function TableSettings({
|
|
|
16420
16469
|
const finished = await archive.start();
|
|
16421
16470
|
if (finished?.done && finished.table_archived) {
|
|
16422
16471
|
setAskingToDelete(false);
|
|
16472
|
+
const name = finished.table_name || "The table";
|
|
16473
|
+
ui.notify?.success(`\u201C${name}\u201D is archived. You can restore it from Trash.`, {
|
|
16474
|
+
label: "Undo",
|
|
16475
|
+
run: () => {
|
|
16476
|
+
void client.recordRestore({ record_id: tableId }).then((back) => {
|
|
16477
|
+
if (back.ok) ui.notify?.success(`\u201C${name}\u201D is back, with everything in it.`);
|
|
16478
|
+
else ui.notify?.error(back.error.message);
|
|
16479
|
+
});
|
|
16480
|
+
}
|
|
16481
|
+
});
|
|
16423
16482
|
onDeleted?.();
|
|
16424
16483
|
}
|
|
16425
16484
|
};
|
|
@@ -16551,31 +16610,20 @@ function TableSettings({
|
|
|
16551
16610
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
16552
16611
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "font-medium", children: "This table" }),
|
|
16553
16612
|
askingToDelete ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
|
|
16554
|
-
/* @__PURE__ */ (0, import_jsx_runtime54.
|
|
16555
|
-
|
|
16556
|
-
|
|
16557
|
-
|
|
16558
|
-
|
|
16559
|
-
|
|
16560
|
-
|
|
16561
|
-
|
|
16562
|
-
|
|
16563
|
-
archive.progress ? `its ${archive.progress.remaining.toLocaleString()} record${archive.progress.remaining === 1 ? "" : "s"}` : "every record in it",
|
|
16564
|
-
" ",
|
|
16565
|
-
"go with it",
|
|
16566
|
-
table.data?.retention_days ? `, kept for ${table.data.retention_days} days` : "",
|
|
16567
|
-
"."
|
|
16568
|
-
] }),
|
|
16569
|
-
archive.progress && (archive.running || archive.passes > 0) ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("p", { className: archive.error ? "text-destructive" : "text-muted-foreground", children: [
|
|
16570
|
-
archive.progress.total - archive.progress.remaining === archive.progress.total ? `All ${archive.progress.total.toLocaleString()} record${archive.progress.total === 1 ? "" : "s"} are put away.` : `${(archive.progress.total - archive.progress.remaining).toLocaleString()} of ${archive.progress.total.toLocaleString()} record${archive.progress.total === 1 ? "" : "s"} put away so far.`,
|
|
16571
|
-
archive.slowedDown ? " The store is busy, so it is taking smaller passes \u2014 it will still finish." : ""
|
|
16572
|
-
] }) : null,
|
|
16573
|
-
archive.interrupted && archive.progress ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "text-muted-foreground", children: archive.error ? `That pass did not finish, so the rest is still here. ${archive.progress.archived_total.toLocaleString()} record${archive.progress.archived_total === 1 ? " is" : "s are"} already archived and ${archive.progress.remaining.toLocaleString()} ${archive.progress.remaining === 1 ? "is" : "are"} left. Nothing was lost \u2014 carry on and it picks up where it stopped.` : `Stopped. ${archive.progress.archived_total.toLocaleString()} record${archive.progress.archived_total === 1 ? " is" : "s are"} archived and ${archive.progress.remaining.toLocaleString()} ${archive.progress.remaining === 1 ? "is" : "are"} left. Carry on whenever you like \u2014 it picks up where it stopped.` }) : null,
|
|
16613
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "text-muted-foreground", "data-archive-confirm": "table", children: archiveConfirmSentence(table.data ? `the table \u201C${tableName(table.data)}\u201D` : "this table") }),
|
|
16614
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "text-muted-foreground", "data-archive-state": "", children: tableArchiveSentence({
|
|
16615
|
+
progress: archive.progress,
|
|
16616
|
+
running: archive.running,
|
|
16617
|
+
interrupted: archive.interrupted,
|
|
16618
|
+
failed: Boolean(archive.error),
|
|
16619
|
+
slowedDown: archive.slowedDown,
|
|
16620
|
+
passesHere: archive.passes
|
|
16621
|
+
}) }),
|
|
16574
16622
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "flex gap-1", children: archive.running ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
|
|
16575
16623
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_design_system47.Button, { size: "sm", variant: "destructive", disabled: true, children: "Archiving\u2026" }),
|
|
16576
16624
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_design_system47.Button, { size: "sm", variant: "ghost", onClick: () => archive.stop(), children: "Stop" })
|
|
16577
16625
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
|
|
16578
|
-
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_design_system47.Button, { size: "sm", variant: "destructive", onClick: () => void startArchive(), children: archive.interrupted ? "Carry on archiving" : "Archive this table" }),
|
|
16626
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_design_system47.Button, { size: "sm", variant: "destructive", onClick: () => void startArchive(), children: archive.interrupted || archive.progress?.in_progress ? "Carry on archiving" : "Archive this table" }),
|
|
16579
16627
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_design_system47.Button, { size: "sm", variant: "ghost", onClick: () => setAskingToDelete(false), children: "Keep it" })
|
|
16580
16628
|
] }) })
|
|
16581
16629
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_design_system47.Button, { size: "sm", variant: "outline", onClick: () => void askToArchive(), children: "Archive this table" }) }),
|
|
@@ -18187,6 +18235,18 @@ function columnDeclarationFor(need, label, options, fields) {
|
|
|
18187
18235
|
if (need.starter.type === "datetime") return { ...base, parity_type: "datetime", kind: "date" };
|
|
18188
18236
|
return { ...base, parity_type: "attachment" };
|
|
18189
18237
|
}
|
|
18238
|
+
var askedFor = /* @__PURE__ */ new Map();
|
|
18239
|
+
var askKey = (tableId, layout) => `${tableId}:${layout}`;
|
|
18240
|
+
function useAskedColumnLands(layout, tableId, fields, chosen, offerable, onMade) {
|
|
18241
|
+
const wanted = askedFor.get(askKey(tableId, layout));
|
|
18242
|
+
const landed = wanted && !chosen ? offerable(fields).find((f) => fieldName(f).trim().toLowerCase() === wanted.trim().toLowerCase()) : void 0;
|
|
18243
|
+
const key = landed?.key ?? null;
|
|
18244
|
+
(0, import_react98.useEffect)(() => {
|
|
18245
|
+
if (!key) return;
|
|
18246
|
+
askedFor.delete(askKey(tableId, layout));
|
|
18247
|
+
onMade(key);
|
|
18248
|
+
}, [key, tableId, layout]);
|
|
18249
|
+
}
|
|
18190
18250
|
var NO_ASSISTANT = "Asking in words needs the AI assistant, which this screen is not connected to.";
|
|
18191
18251
|
function ViewNeeds({ layout, tableId, fields, onMade, className }) {
|
|
18192
18252
|
const need = viewNeedFor(layout);
|
|
@@ -18277,7 +18337,12 @@ function ViewNeeds({ layout, tableId, fields, onMade, className }) {
|
|
|
18277
18337
|
editor,
|
|
18278
18338
|
noAgentSentence: NO_ASSISTANT,
|
|
18279
18339
|
suggestion,
|
|
18280
|
-
...host.onAskForOne ? {
|
|
18340
|
+
...host.onAskForOne ? {
|
|
18341
|
+
onAsk: () => {
|
|
18342
|
+
askedFor.set(askKey(tableId, layout), name);
|
|
18343
|
+
host.onAskForOne?.({ kind: "column", tableId, suggestion });
|
|
18344
|
+
}
|
|
18345
|
+
} : {},
|
|
18281
18346
|
children: rights.structure ? `${need.missing} ${need.does(name)}` : need.missing
|
|
18282
18347
|
}
|
|
18283
18348
|
),
|
|
@@ -18597,6 +18662,17 @@ function Board({
|
|
|
18597
18662
|
() => resolveTableStyle(decorations.data, fields.data ?? [], view.presentation?.style),
|
|
18598
18663
|
[decorations.data, fields.data, view.presentation?.style]
|
|
18599
18664
|
);
|
|
18665
|
+
const askedLayout = view.layout === "grid" ? "kanban" : view.layout;
|
|
18666
|
+
const askedKind = askedLayout === "kanban" ? "choice" : askedLayout === "calendar" ? "date" : "file";
|
|
18667
|
+
const askedChosen = askedLayout === "kanban" ? view.groupField : askedLayout === "calendar" ? view.dateField : view.imageField;
|
|
18668
|
+
useAskedColumnLands(
|
|
18669
|
+
askedLayout,
|
|
18670
|
+
view.subject,
|
|
18671
|
+
fields.data ?? NO_FIELDS,
|
|
18672
|
+
askedChosen,
|
|
18673
|
+
(all2) => offerableFields(all2, askedKind),
|
|
18674
|
+
(key) => onChange(askedLayout === "kanban" ? { groupField: key } : askedLayout === "calendar" ? { dateField: key } : { imageField: key })
|
|
18675
|
+
);
|
|
18600
18676
|
if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(RefusalNotice, { error: fields.error });
|
|
18601
18677
|
if (records.error) return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(RefusalNotice, { error: records.error });
|
|
18602
18678
|
if (fields.loading && !fields.data || records.loading && records.rows.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(import_design_system55.Skeleton, { className: "h-40 w-full" });
|
|
@@ -22234,7 +22310,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
|
|
|
22234
22310
|
}, [load]);
|
|
22235
22311
|
(0, import_react129.useEffect)(() => {
|
|
22236
22312
|
if (title !== "" || !table.data) return;
|
|
22237
|
-
setTitle(existing?.title ?? `Book a ${minutes}-minute ${table.data
|
|
22313
|
+
setTitle(existing?.title ?? `Book a ${minutes}-minute ${singularNoun(table.data, "appointment")}`);
|
|
22238
22314
|
}, [table.data, existing]);
|
|
22239
22315
|
(0, import_react129.useEffect)(() => {
|
|
22240
22316
|
if (!existing) return;
|
|
@@ -22565,6 +22641,7 @@ function BookingSlots({ tableId, activeBookingId, className }) {
|
|
|
22565
22641
|
const [copied, setCopied] = (0, import_react131.useState)(null);
|
|
22566
22642
|
const [shown3, setShown] = (0, import_react131.useState)(null);
|
|
22567
22643
|
const [building, setBuilding] = (0, import_react131.useState)(false);
|
|
22644
|
+
const [changing, setChanging] = (0, import_react131.useState)(null);
|
|
22568
22645
|
const load = (0, import_react131.useCallback)(async () => {
|
|
22569
22646
|
const answered = await client.bookings(tableId ? { table_id: tableId } : {});
|
|
22570
22647
|
if (!answered.ok) {
|
|
@@ -22630,6 +22707,17 @@ function BookingSlots({ tableId, activeBookingId, className }) {
|
|
|
22630
22707
|
] }),
|
|
22631
22708
|
error ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(RefusalNotice, { error }) : null,
|
|
22632
22709
|
activeBookingId && !pages.some((p) => p.form_id === activeBookingId) ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "rounded-md border border-amber-600/40 bg-amber-500/5 px-3 py-2 text-xs leading-relaxed text-amber-700 dark:border-amber-400/40 dark:text-amber-300", children: BOOKING_NOT_HERE_LINE }) : null,
|
|
22710
|
+
changing ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
22711
|
+
BookingBuilder,
|
|
22712
|
+
{
|
|
22713
|
+
tableId: changing.tableId,
|
|
22714
|
+
bookingId: changing.formId,
|
|
22715
|
+
onSaved: () => {
|
|
22716
|
+
void load();
|
|
22717
|
+
},
|
|
22718
|
+
onClose: () => setChanging(null)
|
|
22719
|
+
}
|
|
22720
|
+
) : null,
|
|
22633
22721
|
building && tableId ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
22634
22722
|
BookingBuilder,
|
|
22635
22723
|
{
|
|
@@ -22706,6 +22794,15 @@ function BookingSlots({ tableId, activeBookingId, className }) {
|
|
|
22706
22794
|
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", children: nextInWords(page) }),
|
|
22707
22795
|
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
|
|
22708
22796
|
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(import_design_system68.Button, { size: "sm", variant: "outline", onClick: () => void copy(url, page.form_id), children: copied === page.form_id ? "Copied" : "Copy link" }),
|
|
22797
|
+
mayOpen ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
22798
|
+
import_design_system68.Button,
|
|
22799
|
+
{
|
|
22800
|
+
size: "sm",
|
|
22801
|
+
variant: "ghost",
|
|
22802
|
+
onClick: () => setChanging({ formId: page.form_id, tableId: page.table_id }),
|
|
22803
|
+
children: "Change it"
|
|
22804
|
+
}
|
|
22805
|
+
) : null,
|
|
22709
22806
|
mayOpen ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
22710
22807
|
import_design_system68.Button,
|
|
22711
22808
|
{
|
|
@@ -24542,6 +24639,7 @@ function Invite({ card, onInvited }) {
|
|
|
24542
24639
|
// src/DigestScheduler.tsx
|
|
24543
24640
|
var import_react143 = require("react");
|
|
24544
24641
|
var import_react144 = require("@ai-matrx/records/react");
|
|
24642
|
+
var import_records29 = require("@ai-matrx/records");
|
|
24545
24643
|
var import_design_system74 = require("@ai-matrx/design-system");
|
|
24546
24644
|
|
|
24547
24645
|
// src/scheduleWords.ts
|
|
@@ -24584,6 +24682,12 @@ var CHANNEL_WORDS = {
|
|
|
24584
24682
|
email: "by email \u2014 only if an address is on their account",
|
|
24585
24683
|
sms: "by text \u2014 only if a number is on their account"
|
|
24586
24684
|
};
|
|
24685
|
+
function scheduleParts(schedule) {
|
|
24686
|
+
const words2 = (schedule ?? "").trim().toLowerCase().split(/\s+/);
|
|
24687
|
+
const time = words2.find((w) => /^\d{1,2}:\d{2}$/.test(w)) ?? null;
|
|
24688
|
+
const day = WEEKDAYS.find((d) => words2.some((w) => w.slice(0, 3) === d.slice(0, 3))) ?? null;
|
|
24689
|
+
return { day, time: time ? time.padStart(5, "0") : null };
|
|
24690
|
+
}
|
|
24587
24691
|
function DigestScheduler({
|
|
24588
24692
|
tableId,
|
|
24589
24693
|
savedViewId,
|
|
@@ -24591,7 +24695,8 @@ function DigestScheduler({
|
|
|
24591
24695
|
filters,
|
|
24592
24696
|
onScheduled,
|
|
24593
24697
|
onClose,
|
|
24594
|
-
className
|
|
24698
|
+
className,
|
|
24699
|
+
existing
|
|
24595
24700
|
}) {
|
|
24596
24701
|
const client = (0, import_react144.useRecordsClient)();
|
|
24597
24702
|
const host = useRecordsUi();
|
|
@@ -24599,19 +24704,33 @@ function DigestScheduler({
|
|
|
24599
24704
|
const [cadences, setCadences] = (0, import_react143.useState)([]);
|
|
24600
24705
|
const [members, setMembers] = (0, import_react143.useState)(null);
|
|
24601
24706
|
const [error, setError] = (0, import_react143.useState)(null);
|
|
24602
|
-
const
|
|
24603
|
-
const [
|
|
24604
|
-
|
|
24605
|
-
|
|
24606
|
-
const [
|
|
24607
|
-
|
|
24707
|
+
const was = scheduleParts(existing?.schedule);
|
|
24708
|
+
const [viewId, setViewId] = (0, import_react143.useState)(
|
|
24709
|
+
existing?.saved_view_id ?? savedViewId ?? ""
|
|
24710
|
+
);
|
|
24711
|
+
const [name, setName] = (0, import_react143.useState)(
|
|
24712
|
+
existing?.name ?? (subjectName?.trim() ? `${subjectName.trim()} summary` : "")
|
|
24713
|
+
);
|
|
24714
|
+
const [cadence, setCadence] = (0, import_react143.useState)(
|
|
24715
|
+
["hourly", "daily", "weekly"].includes(existing?.cadence ?? "") ? existing.cadence : "weekly"
|
|
24716
|
+
);
|
|
24717
|
+
const [weekday, setWeekday] = (0, import_react143.useState)(was.day ?? "monday");
|
|
24718
|
+
const [time, setTime] = (0, import_react143.useState)(was.time ?? "08:00");
|
|
24719
|
+
const [timezone, setTimezone] = (0, import_react143.useState)(() => {
|
|
24720
|
+
const kept = existing?.quiet_hours?.tz?.trim();
|
|
24721
|
+
return kept && kept.toUpperCase() !== "UTC" ? kept : ownTimeZone();
|
|
24722
|
+
});
|
|
24608
24723
|
const table = (0, import_react144.useTable)(tableId);
|
|
24609
24724
|
const tableName2 = table.data?.name?.trim() || null;
|
|
24610
|
-
const [channel, setChannel] = (0, import_react143.useState)(
|
|
24611
|
-
|
|
24612
|
-
|
|
24613
|
-
const [
|
|
24614
|
-
const [
|
|
24725
|
+
const [channel, setChannel] = (0, import_react143.useState)(
|
|
24726
|
+
existing?.channel === "email" || existing?.channel === "sms" ? existing.channel : "in_app"
|
|
24727
|
+
);
|
|
24728
|
+
const [quiet, setQuiet] = (0, import_react143.useState)((0, import_records29.hasQuietHours)(existing?.quiet_hours));
|
|
24729
|
+
const [quietFrom, setQuietFrom] = (0, import_react143.useState)(existing?.quiet_hours?.start ?? "22:00");
|
|
24730
|
+
const [quietTo, setQuietTo] = (0, import_react143.useState)(existing?.quiet_hours?.end ?? "07:00");
|
|
24731
|
+
const [recipients, setRecipients] = (0, import_react143.useState)(
|
|
24732
|
+
existing?.recipient_user_id ? [existing.recipient_user_id] : []
|
|
24733
|
+
);
|
|
24615
24734
|
const [saving, setSaving] = (0, import_react143.useState)(false);
|
|
24616
24735
|
const [outcomes, setOutcomes] = (0, import_react143.useState)(null);
|
|
24617
24736
|
const [preview, setPreview] = (0, import_react143.useState)(null);
|
|
@@ -24682,7 +24801,8 @@ function DigestScheduler({
|
|
|
24682
24801
|
schedule,
|
|
24683
24802
|
channel,
|
|
24684
24803
|
quiet_hours: quietHours,
|
|
24685
|
-
...userId === "" ? {} : { recipient_user_id: userId }
|
|
24804
|
+
...userId === "" ? {} : { recipient_user_id: userId },
|
|
24805
|
+
...existing ? { rule_id: existing.rule_id } : {}
|
|
24686
24806
|
}
|
|
24687
24807
|
});
|
|
24688
24808
|
if (written.ok) done.push({ userId, who: label, ruleId: written.data });
|
|
@@ -24705,9 +24825,9 @@ function DigestScheduler({
|
|
|
24705
24825
|
if (views === null && !error) return /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_design_system74.Skeleton, { className: (0, import_design_system74.cn)("h-56 w-full", className) });
|
|
24706
24826
|
return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("section", { className: (0, import_design_system74.cn)("@container flex flex-col gap-3", className), children: [
|
|
24707
24827
|
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("header", { className: "flex items-center gap-2", children: [
|
|
24708
|
-
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("h3", { className: "text-sm font-medium", children: "Send this on a schedule" }),
|
|
24828
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("h3", { className: "text-sm font-medium", children: existing ? "Change this summary" : "Send this on a schedule" }),
|
|
24709
24829
|
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "flex-1" }),
|
|
24710
|
-
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_design_system74.Button, { size: "sm", disabled: saving, onClick: () => void scheduleIt(), children: saving ? "Scheduling\u2026" : "Schedule it" }),
|
|
24830
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_design_system74.Button, { size: "sm", disabled: saving, onClick: () => void scheduleIt(), children: saving ? "Scheduling\u2026" : existing ? "Save the change" : "Schedule it" }),
|
|
24711
24831
|
onClose ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_design_system74.Button, { size: "sm", variant: "ghost", onClick: onClose, children: "Close" }) : null
|
|
24712
24832
|
] }),
|
|
24713
24833
|
error ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(RefusalNotice, { error }) : null,
|
|
@@ -24891,7 +25011,7 @@ function DigestScheduler({
|
|
|
24891
25011
|
// src/SubscriptionsPanel.tsx
|
|
24892
25012
|
var import_react147 = require("react");
|
|
24893
25013
|
var import_react148 = require("@ai-matrx/records/react");
|
|
24894
|
-
var
|
|
25014
|
+
var import_records30 = require("@ai-matrx/records");
|
|
24895
25015
|
var import_design_system76 = require("@ai-matrx/design-system");
|
|
24896
25016
|
|
|
24897
25017
|
// src/WebhooksPanel.tsx
|
|
@@ -24928,13 +25048,16 @@ function WebhooksPanel({ tableId, className }) {
|
|
|
24928
25048
|
const [busy, setBusy] = (0, import_react145.useState)(false);
|
|
24929
25049
|
const [declared2, setDeclared] = (0, import_react145.useState)(null);
|
|
24930
25050
|
const [stopping, setStopping] = (0, import_react145.useState)(null);
|
|
25051
|
+
const [readRefused, setReadRefused] = (0, import_react145.useState)(null);
|
|
24931
25052
|
const load = (0, import_react145.useCallback)(async () => {
|
|
24932
25053
|
const answered = await client.tableWebhooks({ table_id: tableId });
|
|
24933
25054
|
if (!answered.ok) {
|
|
25055
|
+
setReadRefused(answered.error);
|
|
24934
25056
|
setError(answered.error);
|
|
24935
25057
|
setHooks([]);
|
|
24936
25058
|
return;
|
|
24937
25059
|
}
|
|
25060
|
+
setReadRefused(null);
|
|
24938
25061
|
setError(null);
|
|
24939
25062
|
setHooks(answered.data ?? []);
|
|
24940
25063
|
}, [client, tableId]);
|
|
@@ -24963,6 +25086,17 @@ function WebhooksPanel({ tableId, className }) {
|
|
|
24963
25086
|
await load();
|
|
24964
25087
|
};
|
|
24965
25088
|
if (hooks === null) return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(import_design_system75.Skeleton, { className: (0, import_design_system75.cn)("h-16 w-full", className) });
|
|
25089
|
+
const notHers = readRefused?.sqlstate === "42501" && rights.known && !rights.structure;
|
|
25090
|
+
if (notHers) {
|
|
25091
|
+
return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("section", { "data-records-webhooks": "", className: (0, import_design_system75.cn)("flex flex-col gap-2 border-t pt-3", className), children: [
|
|
25092
|
+
/* @__PURE__ */ (0, import_jsx_runtime84.jsx)("header", { className: "flex items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("h3", { className: "text-sm font-medium", children: "Webhooks" }) }),
|
|
25093
|
+
/* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
|
|
25094
|
+
"Which other systems are told about these records is for this table's admins.",
|
|
25095
|
+
" ",
|
|
25096
|
+
rights.why("structure")
|
|
25097
|
+
] })
|
|
25098
|
+
] });
|
|
25099
|
+
}
|
|
24966
25100
|
const mayChange = rights.structure;
|
|
24967
25101
|
const live = hooks.filter((h) => h.is_active);
|
|
24968
25102
|
return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("section", { "data-records-webhooks": "", className: (0, import_design_system75.cn)("flex flex-col gap-2 border-t pt-3", className), children: [
|
|
@@ -25103,6 +25237,7 @@ function SubscriptionsPanel({ tableId, activeRuleId, className }) {
|
|
|
25103
25237
|
const [busy, setBusy] = (0, import_react147.useState)(null);
|
|
25104
25238
|
const [preview, setPreview] = (0, import_react147.useState)(null);
|
|
25105
25239
|
const [scheduling, setScheduling] = (0, import_react147.useState)(false);
|
|
25240
|
+
const [changing, setChanging] = (0, import_react147.useState)(null);
|
|
25106
25241
|
const host = useRecordsUi();
|
|
25107
25242
|
const load = (0, import_react147.useCallback)(async () => {
|
|
25108
25243
|
const answered = await client.subscriptions({ table_id: tableId });
|
|
@@ -25174,6 +25309,18 @@ function SubscriptionsPanel({ tableId, activeRuleId, className }) {
|
|
|
25174
25309
|
onClose: () => setScheduling(false)
|
|
25175
25310
|
}
|
|
25176
25311
|
) : null,
|
|
25312
|
+
changing ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
25313
|
+
DigestScheduler,
|
|
25314
|
+
{
|
|
25315
|
+
tableId,
|
|
25316
|
+
existing: changing,
|
|
25317
|
+
onScheduled: () => {
|
|
25318
|
+
void load();
|
|
25319
|
+
},
|
|
25320
|
+
onClose: () => setChanging(null)
|
|
25321
|
+
},
|
|
25322
|
+
changing.rule_id
|
|
25323
|
+
) : null,
|
|
25177
25324
|
rows.length === 0 && !scheduling ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
25178
25325
|
BuildOrAsk,
|
|
25179
25326
|
{
|
|
@@ -25227,7 +25374,7 @@ function SubscriptionsPanel({ tableId, activeRuleId, className }) {
|
|
|
25227
25374
|
"Last told you ",
|
|
25228
25375
|
new Date(subscription.last_sent_at).toLocaleString()
|
|
25229
25376
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { children: "It has not told you anything yet." }),
|
|
25230
|
-
(0,
|
|
25377
|
+
(0, import_records30.hasQuietHours)(subscription.quiet_hours) ? /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { children: [
|
|
25231
25378
|
"Not between ",
|
|
25232
25379
|
subscription.quiet_hours.start,
|
|
25233
25380
|
" and ",
|
|
@@ -25243,7 +25390,8 @@ function SubscriptionsPanel({ tableId, activeRuleId, className }) {
|
|
|
25243
25390
|
onClick: () => void showOne(subscription),
|
|
25244
25391
|
children: "Send me a preview now"
|
|
25245
25392
|
}
|
|
25246
|
-
)
|
|
25393
|
+
),
|
|
25394
|
+
subscription.mine && subscription.cadence !== "instant" ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_design_system76.Button, { size: "sm", variant: "ghost", onClick: () => setChanging(subscription), children: "Change it" }) : null
|
|
25247
25395
|
] }),
|
|
25248
25396
|
preview && preview.rule_id === subscription.rule_id ? /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "mt-2 rounded-md border bg-muted/40 p-2.5 text-xs", children: [
|
|
25249
25397
|
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("p", { className: "font-medium", children: preview.subject }),
|
|
@@ -25292,7 +25440,7 @@ function SubscriptionsPanel({ tableId, activeRuleId, className }) {
|
|
|
25292
25440
|
// src/FormBuilder.tsx
|
|
25293
25441
|
var import_react153 = require("react");
|
|
25294
25442
|
var import_react154 = require("@ai-matrx/records/react");
|
|
25295
|
-
var
|
|
25443
|
+
var import_records32 = require("@ai-matrx/records");
|
|
25296
25444
|
var import_design_system79 = require("@ai-matrx/design-system");
|
|
25297
25445
|
|
|
25298
25446
|
// src/FormRunner.tsx
|
|
@@ -25657,7 +25805,12 @@ function ThankYou({ form, done, className }) {
|
|
|
25657
25805
|
" ",
|
|
25658
25806
|
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("a", { href: redirect, className: "underline underline-offset-2", children: "Go now" })
|
|
25659
25807
|
] }) : null,
|
|
25660
|
-
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("p", { className: "mt-3 text-xs text-muted-foreground", children: done === "preview" ? redirect ? `This was a preview, so nothing was written. The live form goes on to ${redirect}.` : "This was a preview, so nothing was written." : done === "sent" ?
|
|
25808
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("p", { className: "mt-3 text-xs text-muted-foreground", children: done === "preview" ? redirect ? `This was a preview, so nothing was written. The live form goes on to ${redirect}.` : "This was a preview, so nothing was written." : done === "sent" ? (
|
|
25809
|
+
// SAID TO THE PERSON WHO ANSWERED (lane HANDOVER, 2026-09-29): "Saved to Form 1, with
|
|
25810
|
+
// this form stamped on it" was the owner's bookkeeping read out to a front-desk member
|
|
25811
|
+
// and to strangers. Where it landed is the owner's to see on the table.
|
|
25812
|
+
"Your answers were received."
|
|
25813
|
+
) : done })
|
|
25661
25814
|
] });
|
|
25662
25815
|
}
|
|
25663
25816
|
function Question({
|
|
@@ -25705,7 +25858,7 @@ function Question({
|
|
|
25705
25858
|
// src/NotifyRuleEditor.tsx
|
|
25706
25859
|
var import_react151 = require("react");
|
|
25707
25860
|
var import_react152 = require("@ai-matrx/records/react");
|
|
25708
|
-
var
|
|
25861
|
+
var import_records31 = require("@ai-matrx/records");
|
|
25709
25862
|
var import_design_system78 = require("@ai-matrx/design-system");
|
|
25710
25863
|
var import_jsx_runtime87 = require("react/jsx-runtime");
|
|
25711
25864
|
var CADENCE_WORDS2 = SUBSCRIPTION_CADENCE_LABEL;
|
|
@@ -25856,7 +26009,7 @@ function NotifyRuleEditor({ tableId, seed, chosenRuleId, onChoose, className })
|
|
|
25856
26009
|
"next ",
|
|
25857
26010
|
new Date(held.next_digest_at).toLocaleString()
|
|
25858
26011
|
] }) : null,
|
|
25859
|
-
(0,
|
|
26012
|
+
(0, import_records31.hasQuietHours)(held.quiet_hours) ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
25860
26013
|
"quiet ",
|
|
25861
26014
|
held.quiet_hours.start,
|
|
25862
26015
|
"\u2013",
|
|
@@ -26096,9 +26249,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, startWithOne,
|
|
|
26096
26249
|
(0, import_react153.useEffect)(() => {
|
|
26097
26250
|
if (!startWithOne || started || forms === null || forms.length > 0) return;
|
|
26098
26251
|
if (askableFields(fields.data ?? []).length === 0) return;
|
|
26252
|
+
if (!table.data && !table.error) return;
|
|
26099
26253
|
setStarted(true);
|
|
26100
26254
|
void create(table.data?.name?.trim() ? `${table.data.name.trim()} form` : "Form 1");
|
|
26101
|
-
}, [startWithOne, started, forms, fields.data, create, table.data
|
|
26255
|
+
}, [startWithOne, started, forms, fields.data, create, table.data, table.error]);
|
|
26102
26256
|
if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(RefusalNotice, { error: fields.error, className });
|
|
26103
26257
|
if (error) {
|
|
26104
26258
|
return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
|
|
@@ -26154,7 +26308,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, startWithOne,
|
|
|
26154
26308
|
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
|
|
26155
26309
|
PublishRow,
|
|
26156
26310
|
{
|
|
26157
|
-
url: `${publicOrigin}${(0,
|
|
26311
|
+
url: `${publicOrigin}${(0, import_records32.publicFormPath)(draft.id)}`,
|
|
26158
26312
|
state: draft.state,
|
|
26159
26313
|
mayPublish: rights.structure && !publishGate.blocked,
|
|
26160
26314
|
why: publishGate.why ?? rights.why("structure"),
|
|
@@ -27171,7 +27325,7 @@ function SignBlock({ tableId, recordId, render, className }) {
|
|
|
27171
27325
|
// src/ChartBlock.tsx
|
|
27172
27326
|
var import_react163 = require("react");
|
|
27173
27327
|
var import_recharts = require("recharts");
|
|
27174
|
-
var
|
|
27328
|
+
var import_records33 = require("@ai-matrx/records");
|
|
27175
27329
|
var import_core17 = require("@ai-matrx/records/core");
|
|
27176
27330
|
var import_design_system84 = require("@ai-matrx/design-system");
|
|
27177
27331
|
var import_jsx_runtime93 = require("react/jsx-runtime");
|
|
@@ -27242,7 +27396,7 @@ function ChartBlock({ block, subject, className }) {
|
|
|
27242
27396
|
const kind = block.kind;
|
|
27243
27397
|
const tableId = block.table_id ?? subject;
|
|
27244
27398
|
const measures = block.measures && block.measures.length > 0 ? block.measures : [{ op: "count" }];
|
|
27245
|
-
const primary = (0,
|
|
27399
|
+
const primary = (0, import_records33.measureKey)(measures[0]);
|
|
27246
27400
|
const windows = kind === "stuck" ? null : block.compare ?? null;
|
|
27247
27401
|
const compared = !!windows;
|
|
27248
27402
|
const grain = block.bucket?.by ?? null;
|
|
@@ -28179,7 +28333,7 @@ function TargetControl({
|
|
|
28179
28333
|
// src/FormsPanel.tsx
|
|
28180
28334
|
var import_react166 = require("react");
|
|
28181
28335
|
var import_react167 = require("@ai-matrx/records/react");
|
|
28182
|
-
var
|
|
28336
|
+
var import_records34 = require("@ai-matrx/records");
|
|
28183
28337
|
var import_design_system86 = require("@ai-matrx/design-system");
|
|
28184
28338
|
var import_jsx_runtime95 = require("react/jsx-runtime");
|
|
28185
28339
|
var FORM_NOT_HERE_LINE = "The link named a form this table does not have \u2014 it may have been removed, or it belongs to another table. The forms this table does have are listed here.";
|
|
@@ -28284,7 +28438,7 @@ function FormsPanel({ tableId, activeFormId, className }) {
|
|
|
28284
28438
|
}
|
|
28285
28439
|
) : null,
|
|
28286
28440
|
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("ul", { className: "flex flex-col gap-2", children: forms.map((form) => {
|
|
28287
|
-
const url = `${origin}${(0,
|
|
28441
|
+
const url = `${origin}${(0, import_records34.publicFormPath)(form.form_id)}`;
|
|
28288
28442
|
return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
|
|
28289
28443
|
"li",
|
|
28290
28444
|
{
|
|
@@ -28353,7 +28507,7 @@ var import_design_system88 = require("@ai-matrx/design-system");
|
|
|
28353
28507
|
|
|
28354
28508
|
// src/CaptureRun.tsx
|
|
28355
28509
|
var import_react168 = require("react");
|
|
28356
|
-
var
|
|
28510
|
+
var import_records35 = require("@ai-matrx/records");
|
|
28357
28511
|
var import_react169 = require("@ai-matrx/records/react");
|
|
28358
28512
|
var import_design_system87 = require("@ai-matrx/design-system");
|
|
28359
28513
|
var import_jsx_runtime96 = require("react/jsx-runtime");
|
|
@@ -28408,7 +28562,7 @@ function CaptureRun({ sheetId, face: given, className }) {
|
|
|
28408
28562
|
const [sending, setSending] = (0, import_react168.useState)(false);
|
|
28409
28563
|
const queueRef = (0, import_react168.useRef)(null);
|
|
28410
28564
|
(0, import_react168.useEffect)(() => {
|
|
28411
|
-
const q2 = (0,
|
|
28565
|
+
const q2 = (0, import_records35.openCaptureQueue)({
|
|
28412
28566
|
onChange: (c, all) => {
|
|
28413
28567
|
setCounts(c);
|
|
28414
28568
|
setItems(all);
|
|
@@ -28675,7 +28829,7 @@ function CaptureRun({ sheetId, face: given, className }) {
|
|
|
28675
28829
|
value: String(answers[q.field] ?? ""),
|
|
28676
28830
|
onChange: (e) => {
|
|
28677
28831
|
const raw = e.target.value;
|
|
28678
|
-
const answered2 = field2 ? (0,
|
|
28832
|
+
const answered2 = field2 ? (0, import_records35.coerceTypedAnswer)(field2, raw, { label: q.ask ?? (0, import_records35.coercionLabel)(field2) }) : { value: raw };
|
|
28679
28833
|
setAnswers((held) => ({
|
|
28680
28834
|
...held,
|
|
28681
28835
|
[q.field]: raw === "" ? "" : "refusal" in answered2 ? raw : answered2.value
|
|
@@ -29347,7 +29501,7 @@ function recordsDataSource(client, fallbackSchema = "custom") {
|
|
|
29347
29501
|
|
|
29348
29502
|
// src/TablePage.tsx
|
|
29349
29503
|
var import_react184 = require("react");
|
|
29350
|
-
var
|
|
29504
|
+
var import_records36 = require("@ai-matrx/records");
|
|
29351
29505
|
var import_react185 = require("@ai-matrx/records/react");
|
|
29352
29506
|
var import_design_system93 = require("@ai-matrx/design-system");
|
|
29353
29507
|
|
|
@@ -29722,7 +29876,7 @@ function TableNotHere({
|
|
|
29722
29876
|
return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: (0, import_design_system93.cn)("flex flex-col items-start gap-2 rounded-md border border-dashed p-6", className), children: [
|
|
29723
29877
|
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("p", { className: "text-sm font-medium", children: "This table is archived" }),
|
|
29724
29878
|
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("p", { className: "max-w-prose text-xs text-muted-foreground", children: TABLE_IS_ARCHIVED }),
|
|
29725
|
-
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("p", { className: "text-xs text-muted-foreground", children: (0,
|
|
29879
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("p", { className: "text-xs text-muted-foreground", children: (0, import_records36.archivedByLine)(row) }),
|
|
29726
29880
|
refusal2 ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(RefusalNotice, { error: refusal2 }) : null,
|
|
29727
29881
|
/* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "flex gap-2", children: [
|
|
29728
29882
|
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
|