@ai-matrx/records-ui 0.76.0 → 0.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +88 -0
- package/dist/index.cjs +585 -378
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +567 -340
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -4240,10 +4240,30 @@ import {
|
|
|
4240
4240
|
importCsv,
|
|
4241
4241
|
importXlsx
|
|
4242
4242
|
} from "@ai-matrx/records/core";
|
|
4243
|
-
import {
|
|
4243
|
+
import {
|
|
4244
|
+
Badge as Badge5,
|
|
4245
|
+
Button as Button11,
|
|
4246
|
+
Select as Select3,
|
|
4247
|
+
SelectContent as SelectContent3,
|
|
4248
|
+
SelectItem as SelectItem3,
|
|
4249
|
+
SelectTrigger as SelectTrigger3,
|
|
4250
|
+
SelectValue as SelectValue3,
|
|
4251
|
+
Separator as Separator2,
|
|
4252
|
+
cn as cn12
|
|
4253
|
+
} from "@ai-matrx/design-system";
|
|
4244
4254
|
import { Fragment as Fragment7, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
4245
4255
|
var BATCH = 250;
|
|
4246
4256
|
var SAMPLES = 40;
|
|
4257
|
+
var MAPPING_COLUMNS = "minmax(9rem, 11rem) minmax(14rem, 17rem) minmax(13rem, 1fr) minmax(8rem, 10rem)";
|
|
4258
|
+
var ABSENT = "__absent__";
|
|
4259
|
+
function obviousTitleColumn(columns) {
|
|
4260
|
+
const says = /^(title|name|record|customer|client|company|job|item|subject|label|description)\b|(\bname|\btitle|\bnumber|\bid)$/i;
|
|
4261
|
+
const named = columns.find((c) => says.test(c.header.trim()));
|
|
4262
|
+
if (named) return named.header;
|
|
4263
|
+
const text = columns.find((c) => c.type === "text");
|
|
4264
|
+
if (text) return text.header;
|
|
4265
|
+
return columns[0]?.header ?? null;
|
|
4266
|
+
}
|
|
4247
4267
|
async function sha256(bytes) {
|
|
4248
4268
|
const subtle = globalThis.crypto?.subtle;
|
|
4249
4269
|
if (!subtle) return null;
|
|
@@ -4278,6 +4298,7 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4278
4298
|
const [alreadyRan, setAlreadyRan] = useState13(null);
|
|
4279
4299
|
const [columnsAdded, setColumnsAdded] = useState13(null);
|
|
4280
4300
|
const [show, setShow] = useState13("all");
|
|
4301
|
+
const [ledger, setLedger] = useState13(null);
|
|
4281
4302
|
const declared = fields.data ?? [];
|
|
4282
4303
|
const take = useCallback8(
|
|
4283
4304
|
async (file) => {
|
|
@@ -4288,6 +4309,7 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4288
4309
|
setProposals([]);
|
|
4289
4310
|
setAlreadyRan(null);
|
|
4290
4311
|
setProgress(0);
|
|
4312
|
+
setLedger(null);
|
|
4291
4313
|
try {
|
|
4292
4314
|
const xlsx = file.name.toLowerCase().endsWith(".xlsx");
|
|
4293
4315
|
const bytes = await file.arrayBuffer();
|
|
@@ -4314,6 +4336,11 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4314
4336
|
for (const column of answered.data.columns) {
|
|
4315
4337
|
if (column.matched) next[column.header] = column.field_key;
|
|
4316
4338
|
}
|
|
4339
|
+
const titleKey2 = table.data?.title_field ?? null;
|
|
4340
|
+
if (titleKey2 && !Object.values(next).includes(titleKey2)) {
|
|
4341
|
+
const guess = obviousTitleColumn(answered.data.columns);
|
|
4342
|
+
if (guess) next[guess] = titleKey2;
|
|
4343
|
+
}
|
|
4317
4344
|
setMapping(next);
|
|
4318
4345
|
setPhase("ready");
|
|
4319
4346
|
} catch (thrown) {
|
|
@@ -4321,7 +4348,7 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4321
4348
|
setPhase("waiting");
|
|
4322
4349
|
}
|
|
4323
4350
|
},
|
|
4324
|
-
[client, declared, tableId]
|
|
4351
|
+
[client, declared, tableId, table.data?.title_field]
|
|
4325
4352
|
);
|
|
4326
4353
|
const run = useCallback8(async () => {
|
|
4327
4354
|
if (!plan) return;
|
|
@@ -4329,6 +4356,7 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4329
4356
|
setOutcomes([]);
|
|
4330
4357
|
setColumnsAdded(null);
|
|
4331
4358
|
setProgress(0);
|
|
4359
|
+
setLedger(null);
|
|
4332
4360
|
if (unmapped === "create" && rights.admin) {
|
|
4333
4361
|
setPhase("declaring");
|
|
4334
4362
|
const made = await client.importDeclareColumns({ table_id: tableId, rows, mapping });
|
|
@@ -4364,6 +4392,7 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4364
4392
|
}
|
|
4365
4393
|
const importId = opened.data.import_id;
|
|
4366
4394
|
const collected = [];
|
|
4395
|
+
const told = { seen: 0, written: 0, duplicate: 0, refused: 0 };
|
|
4367
4396
|
let take2 = opened.data.rows_per_call ?? BATCH;
|
|
4368
4397
|
let at = 0;
|
|
4369
4398
|
while (at < rows.length) {
|
|
@@ -4372,11 +4401,17 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4372
4401
|
if (!answered.ok) {
|
|
4373
4402
|
setProblem(answered.error.message);
|
|
4374
4403
|
setOutcomes([...collected]);
|
|
4404
|
+
setLedger({ ...told, final: false });
|
|
4375
4405
|
setPhase("ready");
|
|
4376
4406
|
return;
|
|
4377
4407
|
}
|
|
4378
4408
|
collected.push(...answered.data.outcomes);
|
|
4379
4409
|
setOutcomes([...collected]);
|
|
4410
|
+
told.seen += answered.data.rows_seen;
|
|
4411
|
+
told.written += answered.data.rows_written;
|
|
4412
|
+
told.duplicate += answered.data.rows_duplicate;
|
|
4413
|
+
told.refused += answered.data.rows_refused;
|
|
4414
|
+
setLedger({ ...told, final: false });
|
|
4380
4415
|
at += batch.length;
|
|
4381
4416
|
setProgress(Math.min(at, rows.length));
|
|
4382
4417
|
if (answered.data.rows_per_call) take2 = answered.data.rows_per_call;
|
|
@@ -4389,6 +4424,13 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4389
4424
|
}
|
|
4390
4425
|
setSummary(finished.data.message);
|
|
4391
4426
|
setProposals(finished.data.proposals);
|
|
4427
|
+
setLedger({
|
|
4428
|
+
seen: finished.data.rows_seen,
|
|
4429
|
+
written: finished.data.rows_written,
|
|
4430
|
+
duplicate: finished.data.rows_duplicate,
|
|
4431
|
+
refused: finished.data.rows_refused,
|
|
4432
|
+
final: true
|
|
4433
|
+
});
|
|
4392
4434
|
setPhase("done");
|
|
4393
4435
|
onDone?.(finished.data.rows_written);
|
|
4394
4436
|
}, [client, dedupeKey, fileBytes, fileHash, fileName, format, mapping, onDuplicate, onDone, plan, rows, tableId, unmapped]);
|
|
@@ -4408,6 +4450,10 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4408
4450
|
[outcomes, show]
|
|
4409
4451
|
);
|
|
4410
4452
|
const mappedCount = Object.keys(mapping).length;
|
|
4453
|
+
const titleKey = table.data?.title_field ?? null;
|
|
4454
|
+
const titleMappedTo = titleKey ? Object.entries(mapping).find(([, key]) => key === titleKey)?.[0] ?? null : null;
|
|
4455
|
+
const titleMissing = Boolean(titleKey) && titleMappedTo === null;
|
|
4456
|
+
const titleFieldLabel = (titleKey ? plan?.fields.find((f) => f.key === titleKey)?.label : null) || (titleKey ? declared.find((f) => f.key === titleKey)?.label : null) || "the name column";
|
|
4411
4457
|
const busy = phase === "reading" || phase === "planning" || phase === "declaring" || phase === "writing";
|
|
4412
4458
|
return /* @__PURE__ */ jsxs12("div", { className: cn12("flex min-w-0 flex-col gap-2 text-xs", className), children: [
|
|
4413
4459
|
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
|
|
@@ -4440,55 +4486,107 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4440
4486
|
phase === "reading" ? /* @__PURE__ */ jsx16("p", { className: "text-muted-foreground", children: "Reading the file\u2026" }) : null,
|
|
4441
4487
|
phase === "planning" ? /* @__PURE__ */ jsx16("p", { className: "text-muted-foreground", children: "Working out what each column is\u2026" }) : null,
|
|
4442
4488
|
plan && parsed ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
4443
|
-
/* @__PURE__ */
|
|
4444
|
-
/* @__PURE__ */
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4489
|
+
titleKey ? /* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center gap-2 rounded border bg-muted/40 px-2 py-1.5", children: [
|
|
4490
|
+
/* @__PURE__ */ jsx16("span", { className: "font-medium", children: "What each record is called" }),
|
|
4491
|
+
/* @__PURE__ */ jsxs12(
|
|
4492
|
+
Select3,
|
|
4493
|
+
{
|
|
4494
|
+
value: titleMappedTo ?? "",
|
|
4495
|
+
disabled: busy,
|
|
4496
|
+
onValueChange: (chosen) => {
|
|
4497
|
+
setMapping((m) => {
|
|
4498
|
+
const next = { ...m };
|
|
4499
|
+
for (const [header, key] of Object.entries(next)) {
|
|
4500
|
+
if (key === titleKey) delete next[header];
|
|
4501
|
+
}
|
|
4502
|
+
if (chosen) next[chosen] = titleKey;
|
|
4503
|
+
return next;
|
|
4504
|
+
});
|
|
4505
|
+
},
|
|
4506
|
+
children: [
|
|
4507
|
+
/* @__PURE__ */ jsx16(
|
|
4508
|
+
SelectTrigger3,
|
|
4509
|
+
{
|
|
4510
|
+
size: "sm",
|
|
4511
|
+
"aria-label": "Which column each record is named by",
|
|
4512
|
+
className: "min-w-[14rem]",
|
|
4513
|
+
children: /* @__PURE__ */ jsx16(SelectValue3, { placeholder: "\u2014 choose the column \u2014" })
|
|
4514
|
+
}
|
|
4515
|
+
),
|
|
4516
|
+
/* @__PURE__ */ jsx16(SelectContent3, { children: plan.columns.map((c) => /* @__PURE__ */ jsx16(SelectItem3, { value: c.header, children: c.header }, c.header)) })
|
|
4517
|
+
]
|
|
4518
|
+
}
|
|
4519
|
+
),
|
|
4520
|
+
/* @__PURE__ */ jsx16("span", { className: "text-muted-foreground", children: titleMappedTo ? `goes into ${titleFieldLabel}, so every record this file makes has a name you can read in the grid and on a chip.` : `Nothing goes into ${titleFieldLabel} yet, so every record this file makes would land with no name at all. Pick the column that says what each row IS.` })
|
|
4521
|
+
] }) : null,
|
|
4522
|
+
/* @__PURE__ */ jsx16("div", { className: "w-full overflow-x-auto rounded border", children: /* @__PURE__ */ jsxs12("div", { className: "min-w-[52rem]", children: [
|
|
4523
|
+
/* @__PURE__ */ jsxs12(
|
|
4524
|
+
"div",
|
|
4525
|
+
{
|
|
4526
|
+
className: "grid items-center gap-x-3 border-b bg-muted px-2 py-1 font-medium",
|
|
4527
|
+
style: { gridTemplateColumns: MAPPING_COLUMNS },
|
|
4528
|
+
children: [
|
|
4529
|
+
/* @__PURE__ */ jsx16("span", { children: "Column in the file" }),
|
|
4530
|
+
/* @__PURE__ */ jsx16("span", { children: "Goes to" }),
|
|
4531
|
+
/* @__PURE__ */ jsx16("span", { children: "Kind" }),
|
|
4532
|
+
/* @__PURE__ */ jsx16("span", { children: "First values" })
|
|
4533
|
+
]
|
|
4534
|
+
}
|
|
4535
|
+
),
|
|
4536
|
+
plan.columns.map((column) => {
|
|
4457
4537
|
const to = mapping[column.header] ?? "";
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4538
|
+
const absent = unmapped === "ignore" ? "\u2014 leave it out \u2014" : "\u2014 offer it as a new column \u2014";
|
|
4539
|
+
return /* @__PURE__ */ jsxs12(
|
|
4540
|
+
"div",
|
|
4541
|
+
{
|
|
4542
|
+
className: "grid items-start gap-x-3 border-t px-2 py-1",
|
|
4543
|
+
style: { gridTemplateColumns: MAPPING_COLUMNS },
|
|
4544
|
+
children: [
|
|
4545
|
+
/* @__PURE__ */ jsx16("span", { className: "truncate pt-1.5 font-medium", title: column.header, children: column.header }),
|
|
4546
|
+
/* @__PURE__ */ jsxs12(
|
|
4547
|
+
Select3,
|
|
4548
|
+
{
|
|
4549
|
+
value: to || ABSENT,
|
|
4550
|
+
disabled: busy,
|
|
4551
|
+
onValueChange: (chosen) => {
|
|
4552
|
+
setMapping((m) => {
|
|
4553
|
+
const next = { ...m };
|
|
4554
|
+
if (chosen === ABSENT) delete next[column.header];
|
|
4555
|
+
else next[column.header] = chosen;
|
|
4556
|
+
return next;
|
|
4557
|
+
});
|
|
4558
|
+
},
|
|
4559
|
+
children: [
|
|
4560
|
+
/* @__PURE__ */ jsx16(
|
|
4561
|
+
SelectTrigger3,
|
|
4562
|
+
{
|
|
4563
|
+
size: "sm",
|
|
4564
|
+
"aria-label": `Where ${column.header} goes`,
|
|
4565
|
+
"data-goes-to": column.header,
|
|
4566
|
+
className: "w-full min-w-[14rem]",
|
|
4567
|
+
children: /* @__PURE__ */ jsx16(SelectValue3, {})
|
|
4568
|
+
}
|
|
4569
|
+
),
|
|
4570
|
+
/* @__PURE__ */ jsxs12(SelectContent3, { children: [
|
|
4571
|
+
/* @__PURE__ */ jsx16(SelectItem3, { value: ABSENT, children: absent }),
|
|
4572
|
+
plan.fields.map((f) => /* @__PURE__ */ jsx16(SelectItem3, { value: f.key, children: f.label || f.key }, f.field_id))
|
|
4573
|
+
] })
|
|
4574
|
+
]
|
|
4575
|
+
}
|
|
4576
|
+
),
|
|
4577
|
+
/* @__PURE__ */ jsxs12("div", { className: "pt-1", children: [
|
|
4578
|
+
/* @__PURE__ */ jsx16(Badge5, { variant: column.matched ? "secondary" : "outline", className: "text-[11px] font-normal", children: typeWord(column.type) }),
|
|
4579
|
+
column.unit ? /* @__PURE__ */ jsx16("span", { className: "ml-1 opacity-60", children: column.unit }) : null,
|
|
4580
|
+
/* @__PURE__ */ jsx16("p", { className: "mt-0.5 text-muted-foreground", children: column.why }),
|
|
4581
|
+
column.ambiguous ? /* @__PURE__ */ jsx16("p", { className: "text-destructive", children: "Check a date you know before you run this." }) : null,
|
|
4582
|
+
column.collides_with ? /* @__PURE__ */ jsx16("p", { className: "text-destructive", children: "Two columns in this file would make the same column." }) : null
|
|
4583
|
+
] }),
|
|
4584
|
+
/* @__PURE__ */ jsx16("span", { className: "truncate pt-1.5 text-muted-foreground", children: (column.samples ?? []).slice(0, 3).map(String).join(" \xB7 ") })
|
|
4585
|
+
]
|
|
4586
|
+
},
|
|
4587
|
+
column.header
|
|
4588
|
+
);
|
|
4589
|
+
})
|
|
4492
4590
|
] }) }),
|
|
4493
4591
|
/* @__PURE__ */ jsx16(Separator2, {}),
|
|
4494
4592
|
/* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
@@ -4546,13 +4644,18 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4546
4644
|
] })
|
|
4547
4645
|
] }),
|
|
4548
4646
|
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
|
|
4549
|
-
/* @__PURE__ */ jsx16(
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4647
|
+
/* @__PURE__ */ jsx16(
|
|
4648
|
+
Button11,
|
|
4649
|
+
{
|
|
4650
|
+
size: "sm",
|
|
4651
|
+
disabled: busy || !rights.write || rows.length === 0 || titleMissing,
|
|
4652
|
+
onClick: () => void run(),
|
|
4653
|
+
children: phase === "declaring" ? "Adding the columns\u2026" : phase === "writing" ? `Writing\u2026 ${progress} of ${rows.length}` : `Import ${rows.length} row${rows.length === 1 ? "" : "s"}`
|
|
4654
|
+
}
|
|
4655
|
+
),
|
|
4656
|
+
/* @__PURE__ */ jsxs12("span", { className: cn12("text-muted-foreground", titleMissing && "text-destructive"), children: [
|
|
4657
|
+
titleMissing ? `Nothing goes into ${titleFieldLabel} yet, so these records would have no name. Choose the column above, then this will run.` : `${mappedCount} of ${plan.columns.length} columns go into this table`,
|
|
4658
|
+
fileHash || titleMissing ? "" : " \xB7 this browser cannot recognise the file again, so importing it twice would write it twice"
|
|
4556
4659
|
] })
|
|
4557
4660
|
] })
|
|
4558
4661
|
] }) : null,
|
|
@@ -4570,27 +4673,31 @@ function ImportWizard({ tableId, onDone, className }) {
|
|
|
4570
4673
|
] }) : null
|
|
4571
4674
|
] }) : null,
|
|
4572
4675
|
alreadyRan ? /* @__PURE__ */ jsx16("p", { className: "text-muted-foreground", children: alreadyRan }) : null,
|
|
4573
|
-
outcomes.length > 0 || summary ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
4676
|
+
outcomes.length > 0 || summary || ledger ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
4574
4677
|
/* @__PURE__ */ jsx16(Separator2, {}),
|
|
4575
4678
|
/* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
4576
|
-
/* @__PURE__ */
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
counts.duplicate,
|
|
4580
|
-
" already here \xB7 ",
|
|
4581
|
-
counts.refused,
|
|
4582
|
-
" refused"
|
|
4583
|
-
] }),
|
|
4584
|
-
counts.refused + counts.duplicate > 0 ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
4679
|
+
/* @__PURE__ */ jsx16("span", { children: ledger ? `${ledger.written} landed \xB7 ${ledger.duplicate} already here \xB7 ${ledger.refused} refused, of ${ledger.seen} row${ledger.seen === 1 ? "" : "s"} offered` : `${counts.landed} landed \xB7 ${counts.duplicate} already here \xB7 ${counts.refused} refused` }),
|
|
4680
|
+
ledger && !ledger.final && phase !== "writing" ? /* @__PURE__ */ jsx16("span", { className: "text-destructive", children: "The run stopped here, so the rest of the file was never offered \u2014 these are the rows that were dealt with before it stopped, not the whole file." }) : null,
|
|
4681
|
+
(ledger ? ledger.refused + ledger.duplicate : counts.refused + counts.duplicate) > 0 ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
4585
4682
|
/* @__PURE__ */ jsx16("button", { type: "button", className: cn12("underline underline-offset-2", show === "all" && "font-medium"), onClick: () => setShow("all"), children: "everything that did not land" }),
|
|
4586
4683
|
/* @__PURE__ */ jsx16("button", { type: "button", className: cn12("underline underline-offset-2", show === "refused" && "font-medium"), onClick: () => setShow("refused"), children: "refused" }),
|
|
4587
4684
|
/* @__PURE__ */ jsx16("button", { type: "button", className: cn12("underline underline-offset-2", show === "duplicate" && "font-medium"), onClick: () => setShow("duplicate"), children: "already here" })
|
|
4588
4685
|
] }) : null
|
|
4589
4686
|
] }),
|
|
4590
4687
|
summary ? /* @__PURE__ */ jsx16("p", { className: "text-muted-foreground", children: summary }) : null,
|
|
4688
|
+
ledger && show === "all" && ledger.refused + ledger.duplicate > interesting.length ? /* @__PURE__ */ jsxs12("p", { className: "text-muted-foreground", children: [
|
|
4689
|
+
interesting.length,
|
|
4690
|
+
" of the ",
|
|
4691
|
+
ledger.refused + ledger.duplicate,
|
|
4692
|
+
" row",
|
|
4693
|
+
ledger.refused + ledger.duplicate === 1 ? " that" : "s that",
|
|
4694
|
+
" did not land",
|
|
4695
|
+
interesting.length === 1 ? " is" : " are",
|
|
4696
|
+
" listed below by their line in your file \u2014 the store keeps the rest with this run and does not hand every one of them back at once."
|
|
4697
|
+
] }) : null,
|
|
4591
4698
|
interesting.length > 0 ? /* @__PURE__ */ jsx16("div", { className: "max-h-64 overflow-auto rounded border", children: /* @__PURE__ */ jsxs12("table", { className: "w-full", children: [
|
|
4592
4699
|
/* @__PURE__ */ jsx16("thead", { className: "sticky top-0 bg-muted", children: /* @__PURE__ */ jsxs12("tr", { children: [
|
|
4593
|
-
/* @__PURE__ */ jsx16("th", { className: "px-2 py-1 text-left font-medium", children: "
|
|
4700
|
+
/* @__PURE__ */ jsx16("th", { className: "px-2 py-1 text-left font-medium", children: "Line in your file" }),
|
|
4594
4701
|
/* @__PURE__ */ jsx16("th", { className: "px-2 py-1 text-left font-medium", children: "What happened" }),
|
|
4595
4702
|
/* @__PURE__ */ jsx16("th", { className: "px-2 py-1 text-left font-medium", children: "The row in your file" })
|
|
4596
4703
|
] }) }),
|
|
@@ -4803,13 +4910,13 @@ import {
|
|
|
4803
4910
|
Button as Button13,
|
|
4804
4911
|
Checkbox as Checkbox4,
|
|
4805
4912
|
Label as Label4,
|
|
4806
|
-
Select as
|
|
4807
|
-
SelectContent as
|
|
4913
|
+
Select as Select4,
|
|
4914
|
+
SelectContent as SelectContent4,
|
|
4808
4915
|
SelectGroup,
|
|
4809
|
-
SelectItem as
|
|
4916
|
+
SelectItem as SelectItem4,
|
|
4810
4917
|
SelectLabel,
|
|
4811
|
-
SelectTrigger as
|
|
4812
|
-
SelectValue as
|
|
4918
|
+
SelectTrigger as SelectTrigger4,
|
|
4919
|
+
SelectValue as SelectValue4,
|
|
4813
4920
|
Separator as Separator4,
|
|
4814
4921
|
cn as cn14
|
|
4815
4922
|
} from "@ai-matrx/design-system";
|
|
@@ -4974,16 +5081,16 @@ function FieldEditor({ tableId, field, onSaved, onCancel, onRemoved, className }
|
|
|
4974
5081
|
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1", children: [
|
|
4975
5082
|
/* @__PURE__ */ jsx18(Label4, { className: "text-xs", children: "What it holds" }),
|
|
4976
5083
|
/* @__PURE__ */ jsxs14(
|
|
4977
|
-
|
|
5084
|
+
Select4,
|
|
4978
5085
|
{
|
|
4979
5086
|
value: type,
|
|
4980
5087
|
disabled: editing,
|
|
4981
5088
|
onValueChange: (next) => setType(next),
|
|
4982
5089
|
children: [
|
|
4983
|
-
/* @__PURE__ */ jsx18(
|
|
4984
|
-
/* @__PURE__ */ jsx18(
|
|
5090
|
+
/* @__PURE__ */ jsx18(SelectTrigger4, { size: "sm", "aria-label": "What this field holds", children: /* @__PURE__ */ jsx18(SelectValue4, {}) }),
|
|
5091
|
+
/* @__PURE__ */ jsx18(SelectContent4, { children: FIELD_TYPE_GROUPS.map((group) => /* @__PURE__ */ jsxs14(SelectGroup, { children: [
|
|
4985
5092
|
/* @__PURE__ */ jsx18(SelectLabel, { children: group }),
|
|
4986
|
-
FIELD_TYPE_CHOICES.filter((c) => c.group === group).map((c) => /* @__PURE__ */ jsx18(
|
|
5093
|
+
FIELD_TYPE_CHOICES.filter((c) => c.group === group).map((c) => /* @__PURE__ */ jsx18(SelectItem4, { value: c.id, children: c.label }, c.id))
|
|
4987
5094
|
] }, group)) })
|
|
4988
5095
|
]
|
|
4989
5096
|
}
|
|
@@ -5063,16 +5170,16 @@ function FieldEditor({ tableId, field, onSaved, onCancel, onRemoved, className }
|
|
|
5063
5170
|
/* @__PURE__ */ jsxs14("div", { className: "grid gap-3 sm:grid-cols-2", children: [
|
|
5064
5171
|
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1", children: [
|
|
5065
5172
|
/* @__PURE__ */ jsx18(Label4, { className: "text-xs", children: "Who can see what is in it" }),
|
|
5066
|
-
/* @__PURE__ */ jsxs14(
|
|
5067
|
-
/* @__PURE__ */ jsx18(
|
|
5068
|
-
/* @__PURE__ */ jsx18(
|
|
5173
|
+
/* @__PURE__ */ jsxs14(Select4, { value: sensitivity, onValueChange: setSensitivity, children: [
|
|
5174
|
+
/* @__PURE__ */ jsx18(SelectTrigger4, { size: "sm", "aria-label": "Who can see what is in it", children: /* @__PURE__ */ jsx18(SelectValue4, {}) }),
|
|
5175
|
+
/* @__PURE__ */ jsx18(SelectContent4, { children: SENSITIVITIES.map((row) => /* @__PURE__ */ jsx18(SelectItem4, { value: row.value, children: row.label }, row.value)) })
|
|
5069
5176
|
] })
|
|
5070
5177
|
] }),
|
|
5071
5178
|
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1", children: [
|
|
5072
5179
|
/* @__PURE__ */ jsx18(Label4, { className: "text-xs", children: "Can an assistant read it" }),
|
|
5073
|
-
/* @__PURE__ */ jsxs14(
|
|
5074
|
-
/* @__PURE__ */ jsx18(
|
|
5075
|
-
/* @__PURE__ */ jsx18(
|
|
5180
|
+
/* @__PURE__ */ jsxs14(Select4, { value: contextPolicy, onValueChange: setContextPolicy, children: [
|
|
5181
|
+
/* @__PURE__ */ jsx18(SelectTrigger4, { size: "sm", "aria-label": "Can an assistant read it", children: /* @__PURE__ */ jsx18(SelectValue4, {}) }),
|
|
5182
|
+
/* @__PURE__ */ jsx18(SelectContent4, { children: AGENT_VISIBILITY.map((row) => /* @__PURE__ */ jsx18(SelectItem4, { value: row.value, children: row.label }, row.value)) })
|
|
5076
5183
|
] })
|
|
5077
5184
|
] })
|
|
5078
5185
|
] }),
|
|
@@ -5095,13 +5202,13 @@ function FieldEditor({ tableId, field, onSaved, onCancel, onRemoved, className }
|
|
|
5095
5202
|
rules.length === 0 ? /* @__PURE__ */ jsx18("p", { className: "text-muted-foreground", children: "No checks. Anything this kind of column can hold will be accepted." }) : null,
|
|
5096
5203
|
rules.map((rule, index) => /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-1", children: [
|
|
5097
5204
|
/* @__PURE__ */ jsxs14(
|
|
5098
|
-
|
|
5205
|
+
Select4,
|
|
5099
5206
|
{
|
|
5100
5207
|
value: rule.kind,
|
|
5101
5208
|
onValueChange: (kind) => setRules(rules.map((r, i) => i === index ? { ...r, kind } : r)),
|
|
5102
5209
|
children: [
|
|
5103
|
-
/* @__PURE__ */ jsx18(
|
|
5104
|
-
/* @__PURE__ */ jsx18(
|
|
5210
|
+
/* @__PURE__ */ jsx18(SelectTrigger4, { size: "sm", className: "w-52", "aria-label": `Check ${index + 1}`, children: /* @__PURE__ */ jsx18(SelectValue4, {}) }),
|
|
5211
|
+
/* @__PURE__ */ jsx18(SelectContent4, { children: RULE_KINDS.map((row) => /* @__PURE__ */ jsx18(SelectItem4, { value: row.kind, children: row.label }, row.kind)) })
|
|
5105
5212
|
]
|
|
5106
5213
|
}
|
|
5107
5214
|
),
|
|
@@ -5277,9 +5384,9 @@ function TypeQuestions(props) {
|
|
|
5277
5384
|
return /* @__PURE__ */ jsxs14("div", { className: "grid gap-3 sm:grid-cols-2", children: [
|
|
5278
5385
|
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1", children: [
|
|
5279
5386
|
/* @__PURE__ */ jsx18(Label4, { className: "text-xs", children: type === "rollup" ? "Across the records in" : "Read it from" }),
|
|
5280
|
-
/* @__PURE__ */ jsxs14(
|
|
5281
|
-
/* @__PURE__ */ jsx18(
|
|
5282
|
-
/* @__PURE__ */ jsx18(
|
|
5387
|
+
/* @__PURE__ */ jsxs14(Select4, { value: props.via, onValueChange: props.setVia, children: [
|
|
5388
|
+
/* @__PURE__ */ jsx18(SelectTrigger4, { size: "sm", "aria-label": type === "rollup" ? "Across the records in" : "Read it from", children: /* @__PURE__ */ jsx18(SelectValue4, { placeholder: "Choose a column" }) }),
|
|
5389
|
+
/* @__PURE__ */ jsx18(SelectContent4, { children: usable.map((f) => /* @__PURE__ */ jsxs14(SelectItem4, { value: f.key, children: [
|
|
5283
5390
|
fieldName(f),
|
|
5284
5391
|
type === "rollup" && !f.multi ? " \u2014 holds one" : ""
|
|
5285
5392
|
] }, f.id)) })
|
|
@@ -5296,9 +5403,9 @@ function TypeQuestions(props) {
|
|
|
5296
5403
|
}
|
|
5297
5404
|
) : /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1", children: [
|
|
5298
5405
|
/* @__PURE__ */ jsx18(Label4, { className: "text-xs", children: "What to work out" }),
|
|
5299
|
-
/* @__PURE__ */ jsxs14(
|
|
5300
|
-
/* @__PURE__ */ jsx18(
|
|
5301
|
-
/* @__PURE__ */ jsx18(
|
|
5406
|
+
/* @__PURE__ */ jsxs14(Select4, { value: props.agg, onValueChange: (v) => props.setAgg(v), children: [
|
|
5407
|
+
/* @__PURE__ */ jsx18(SelectTrigger4, { size: "sm", "aria-label": "What to work out", children: /* @__PURE__ */ jsx18(SelectValue4, {}) }),
|
|
5408
|
+
/* @__PURE__ */ jsx18(SelectContent4, { children: ROLLUP_OPERATIONS.map((row) => /* @__PURE__ */ jsx18(SelectItem4, { value: row.value, children: row.label }, row.value)) })
|
|
5302
5409
|
] }),
|
|
5303
5410
|
props.agg !== "count" ? /* @__PURE__ */ jsx18(
|
|
5304
5411
|
ValueOnTheOtherSide,
|
|
@@ -5321,9 +5428,9 @@ function TypeQuestions(props) {
|
|
|
5321
5428
|
return /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-2", children: [
|
|
5322
5429
|
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1", children: [
|
|
5323
5430
|
/* @__PURE__ */ jsx18(Label4, { className: "text-xs", children: "What to do" }),
|
|
5324
|
-
/* @__PURE__ */ jsxs14(
|
|
5325
|
-
/* @__PURE__ */ jsx18(
|
|
5326
|
-
/* @__PURE__ */ jsx18(
|
|
5431
|
+
/* @__PURE__ */ jsxs14(Select4, { value: props.formulaOp, onValueChange: props.setFormulaOp, children: [
|
|
5432
|
+
/* @__PURE__ */ jsx18(SelectTrigger4, { size: "sm", className: "max-w-[18rem]", "aria-label": "What to do", children: /* @__PURE__ */ jsx18(SelectValue4, {}) }),
|
|
5433
|
+
/* @__PURE__ */ jsx18(SelectContent4, { children: FORMULA_OPERATIONS.map((row) => /* @__PURE__ */ jsx18(SelectItem4, { value: row.value, children: row.label }, row.value)) })
|
|
5327
5434
|
] })
|
|
5328
5435
|
] }),
|
|
5329
5436
|
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1", children: [
|
|
@@ -5368,9 +5475,9 @@ function ValueOnTheOtherSide({
|
|
|
5368
5475
|
const body = !relation ? /* @__PURE__ */ jsx18("p", { className: "text-[11px] text-muted-foreground", children: "Choose the column above first." }) : stillAsking ? /* @__PURE__ */ jsx18("p", { className: "text-[11px] text-muted-foreground", children: "Reading that table's columns\u2026" }) : offered.length === 0 ? /* @__PURE__ */ jsxs14("p", { className: "text-[11px] text-muted-foreground", children: [
|
|
5369
5476
|
fieldName(relation),
|
|
5370
5477
|
" points at a table that has no columns to read yet. Add one there first."
|
|
5371
|
-
] }) : /* @__PURE__ */ jsxs14(
|
|
5372
|
-
/* @__PURE__ */ jsx18(
|
|
5373
|
-
/* @__PURE__ */ jsx18(
|
|
5478
|
+
] }) : /* @__PURE__ */ jsxs14(Select4, { value, onValueChange: onChange, children: [
|
|
5479
|
+
/* @__PURE__ */ jsx18(SelectTrigger4, { size: "sm", "aria-label": label, children: /* @__PURE__ */ jsx18(SelectValue4, { placeholder: "Choose a column" }) }),
|
|
5480
|
+
/* @__PURE__ */ jsx18(SelectContent4, { children: offered.map((column) => /* @__PURE__ */ jsx18(SelectItem4, { value: column.key, children: column.name }, column.key)) })
|
|
5374
5481
|
] });
|
|
5375
5482
|
if (compact) return /* @__PURE__ */ jsx18("div", { className: "mt-1 flex flex-col gap-1", children: body });
|
|
5376
5483
|
return /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1", children: [
|
|
@@ -5977,8 +6084,8 @@ import { useState as useState18 } from "react";
|
|
|
5977
6084
|
import {
|
|
5978
6085
|
useFieldMutation as useFieldMutation2,
|
|
5979
6086
|
useFields as useFields8,
|
|
5980
|
-
|
|
5981
|
-
|
|
6087
|
+
useTable as useTable6,
|
|
6088
|
+
useTableArchive
|
|
5982
6089
|
} from "@ai-matrx/records/react";
|
|
5983
6090
|
import { Badge as Badge6, Button as Button16, Separator as Separator6, cn as cn16 } from "@ai-matrx/design-system";
|
|
5984
6091
|
import { Fragment as Fragment10, jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
@@ -5993,8 +6100,8 @@ function TableSettings({
|
|
|
5993
6100
|
const table = useTable6(tableId);
|
|
5994
6101
|
const fields = useFields8(tableId);
|
|
5995
6102
|
const rights = useTableRights(table.data);
|
|
5996
|
-
const mutation = useRecordMutation();
|
|
5997
6103
|
const shape = useFieldMutation2();
|
|
6104
|
+
const archive = useTableArchive(tableId);
|
|
5998
6105
|
const [editing, setEditing] = useState18(null);
|
|
5999
6106
|
const [askingToDelete, setAskingToDelete] = useState18(false);
|
|
6000
6107
|
const [askingToRemove, setAskingToRemove] = useState18(null);
|
|
@@ -6019,10 +6126,16 @@ function TableSettings({
|
|
|
6019
6126
|
table.reload();
|
|
6020
6127
|
}
|
|
6021
6128
|
};
|
|
6022
|
-
const
|
|
6023
|
-
const
|
|
6024
|
-
|
|
6025
|
-
|
|
6129
|
+
const startArchive = async () => {
|
|
6130
|
+
const finished = await archive.start();
|
|
6131
|
+
if (finished?.done && finished.table_archived) {
|
|
6132
|
+
setAskingToDelete(false);
|
|
6133
|
+
onDeleted?.();
|
|
6134
|
+
}
|
|
6135
|
+
};
|
|
6136
|
+
const askToArchive = async () => {
|
|
6137
|
+
setAskingToDelete(true);
|
|
6138
|
+
await archive.preview();
|
|
6026
6139
|
};
|
|
6027
6140
|
if (enriching) {
|
|
6028
6141
|
return /* @__PURE__ */ jsxs17("div", { className, children: [
|
|
@@ -6058,7 +6171,6 @@ function TableSettings({
|
|
|
6058
6171
|
/* @__PURE__ */ jsx21("span", { className: "text-muted-foreground", children: rows.length }),
|
|
6059
6172
|
/* @__PURE__ */ jsx21(Button16, { size: "sm", variant: "outline", className: "ml-auto", onClick: () => setEditing("new"), children: "Add a field" })
|
|
6060
6173
|
] }),
|
|
6061
|
-
mutation.error ? /* @__PURE__ */ jsx21(RefusalNotice, { error: mutation.error }) : null,
|
|
6062
6174
|
shape.error ? /* @__PURE__ */ jsx21(RefusalNotice, { error: shape.error }) : null,
|
|
6063
6175
|
askingToRemove ? /* @__PURE__ */ jsxs17("div", { className: "flex flex-wrap items-center gap-2 rounded border border-destructive/40 px-2 py-1.5", children: [
|
|
6064
6176
|
/* @__PURE__ */ jsxs17("span", { className: "text-destructive", children: [
|
|
@@ -6149,21 +6261,32 @@ function TableSettings({
|
|
|
6149
6261
|
/* @__PURE__ */ jsx21("span", { className: "font-medium", children: "This table" }),
|
|
6150
6262
|
askingToDelete ? /* @__PURE__ */ jsxs17(Fragment10, { children: [
|
|
6151
6263
|
/* @__PURE__ */ jsxs17("p", { className: "text-muted-foreground", children: [
|
|
6152
|
-
"
|
|
6264
|
+
"Archiving ",
|
|
6153
6265
|
table.data ? tableName(table.data) : "this table",
|
|
6154
6266
|
" takes it out of everyone's list, with its ",
|
|
6155
6267
|
rows.length,
|
|
6156
6268
|
" field",
|
|
6157
6269
|
rows.length === 1 ? "" : "s",
|
|
6158
|
-
" and
|
|
6159
|
-
|
|
6270
|
+
" and",
|
|
6271
|
+
" ",
|
|
6272
|
+
archive.progress ? `its ${archive.progress.remaining.toLocaleString()} record${archive.progress.remaining === 1 ? "" : "s"}` : "every record in it",
|
|
6273
|
+
".",
|
|
6274
|
+
table.data?.retention_days ? ` The store keeps them for ${table.data.retention_days} days, so it can still be brought back.` : " The store keeps them, so it can still be brought back."
|
|
6160
6275
|
] }),
|
|
6161
|
-
/* @__PURE__ */ jsxs17("
|
|
6162
|
-
|
|
6276
|
+
archive.progress && (archive.running || archive.passes > 0) ? /* @__PURE__ */ jsxs17("p", { className: archive.error ? "text-destructive" : "text-muted-foreground", children: [
|
|
6277
|
+
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.`,
|
|
6278
|
+
archive.slowedDown ? " The store is busy, so it is taking smaller passes \u2014 it will still finish." : ""
|
|
6279
|
+
] }) : null,
|
|
6280
|
+
archive.interrupted && archive.progress ? /* @__PURE__ */ jsx21("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,
|
|
6281
|
+
/* @__PURE__ */ jsx21("div", { className: "flex gap-1", children: archive.running ? /* @__PURE__ */ jsxs17(Fragment10, { children: [
|
|
6282
|
+
/* @__PURE__ */ jsx21(Button16, { size: "sm", variant: "destructive", disabled: true, children: "Archiving\u2026" }),
|
|
6283
|
+
/* @__PURE__ */ jsx21(Button16, { size: "sm", variant: "ghost", onClick: () => archive.stop(), children: "Stop" })
|
|
6284
|
+
] }) : /* @__PURE__ */ jsxs17(Fragment10, { children: [
|
|
6285
|
+
/* @__PURE__ */ jsx21(Button16, { size: "sm", variant: "destructive", onClick: () => void startArchive(), children: archive.interrupted ? "Carry on archiving" : "Archive this table" }),
|
|
6163
6286
|
/* @__PURE__ */ jsx21(Button16, { size: "sm", variant: "ghost", onClick: () => setAskingToDelete(false), children: "Keep it" })
|
|
6164
|
-
] })
|
|
6165
|
-
] }) : /* @__PURE__ */ jsx21("div", { children: /* @__PURE__ */ jsx21(Button16, { size: "sm", variant: "outline", onClick: () =>
|
|
6166
|
-
|
|
6287
|
+
] }) })
|
|
6288
|
+
] }) : /* @__PURE__ */ jsx21("div", { children: /* @__PURE__ */ jsx21(Button16, { size: "sm", variant: "outline", onClick: () => void askToArchive(), children: "Archive this table" }) }),
|
|
6289
|
+
archive.error ? /* @__PURE__ */ jsx21(RefusalNotice, { error: archive.error }) : null
|
|
6167
6290
|
] })
|
|
6168
6291
|
] });
|
|
6169
6292
|
}
|
|
@@ -6305,7 +6428,7 @@ import { useEffect as useEffect11, useMemo as useMemo16, useState as useState21
|
|
|
6305
6428
|
import {
|
|
6306
6429
|
useFields as useFields9,
|
|
6307
6430
|
useRecord,
|
|
6308
|
-
useRecordMutation
|
|
6431
|
+
useRecordMutation
|
|
6309
6432
|
} from "@ai-matrx/records/react";
|
|
6310
6433
|
import { predictWriteRefusals } from "@ai-matrx/records/core";
|
|
6311
6434
|
import { Button as Button17, Separator as Separator7, cn as cn18 } from "@ai-matrx/design-system";
|
|
@@ -6494,7 +6617,7 @@ function RecordForm({
|
|
|
6494
6617
|
const host = useRecordsUi();
|
|
6495
6618
|
const fields = useFields9(tableId, recordType);
|
|
6496
6619
|
const existing = useRecord(recordId ?? null);
|
|
6497
|
-
const mutation =
|
|
6620
|
+
const mutation = useRecordMutation();
|
|
6498
6621
|
const [draft, setDraft] = useState21({});
|
|
6499
6622
|
const [touched, setTouched] = useState21(false);
|
|
6500
6623
|
const loaded = useRecordVersion(recordId ?? null);
|
|
@@ -7471,6 +7594,7 @@ function ViewSwitcher({
|
|
|
7471
7594
|
)
|
|
7472
7595
|
] });
|
|
7473
7596
|
}
|
|
7597
|
+
var UNUSUAL_FIELD_NOTE = "an unusual column to use here";
|
|
7474
7598
|
function offerableFields(all, want) {
|
|
7475
7599
|
return all.filter((field) => {
|
|
7476
7600
|
const kind = editorKindFor(field);
|
|
@@ -7606,10 +7730,7 @@ function FieldPicker({
|
|
|
7606
7730
|
children: [
|
|
7607
7731
|
/* @__PURE__ */ jsx27("option", { value: "", children: "Choose a field" }),
|
|
7608
7732
|
offerable.map((field) => /* @__PURE__ */ jsx27("option", { value: field.key, children: fieldName(field) }, field.key)),
|
|
7609
|
-
unusual ? /* @__PURE__ */
|
|
7610
|
-
fieldName(unusual),
|
|
7611
|
-
" \u2014 an unusual column to use here"
|
|
7612
|
-
] }, unusual.key) : null
|
|
7733
|
+
unusual ? /* @__PURE__ */ jsx27("option", { value: unusual.key, children: `${fieldName(unusual)} \u2014 ${UNUSUAL_FIELD_NOTE}` }, unusual.key) : null
|
|
7613
7734
|
]
|
|
7614
7735
|
}
|
|
7615
7736
|
),
|
|
@@ -11450,8 +11571,35 @@ function SubscriptionsPanel({ tableId, className }) {
|
|
|
11450
11571
|
}
|
|
11451
11572
|
|
|
11452
11573
|
// src/FormBuilder.tsx
|
|
11453
|
-
import { useCallback as useCallback25, useEffect as
|
|
11454
|
-
import { useFields as useFields18, useRecordsClient as
|
|
11574
|
+
import { useCallback as useCallback25, useEffect as useEffect28, useMemo as useMemo26, useState as useState41 } from "react";
|
|
11575
|
+
import { useFields as useFields18, useRecordsClient as useRecordsClient28, useTable as useTable14 } from "@ai-matrx/records/react";
|
|
11576
|
+
|
|
11577
|
+
// src/publish-gate.ts
|
|
11578
|
+
import { useEffect as useEffect26, useState as useState39 } from "react";
|
|
11579
|
+
import { useRecordsClient as useRecordsClient27 } from "@ai-matrx/records/react";
|
|
11580
|
+
var PUBLISH_NEEDS_THE_STORE_ON = "This organization has its record store switched off, so publishing would hand you a link that opens nothing. An owner or an administrator turns it on under Database settings, on the unified data screen \u2014 everything you have already built here is kept and starts working the moment they do.";
|
|
11581
|
+
function usePublishGate() {
|
|
11582
|
+
const client = useRecordsClient27();
|
|
11583
|
+
const [storeOpen, setStoreOpen] = useState39(null);
|
|
11584
|
+
useEffect26(() => {
|
|
11585
|
+
let alive = true;
|
|
11586
|
+
void (async () => {
|
|
11587
|
+
const answered = await client.storeIsOpen();
|
|
11588
|
+
if (!alive) return;
|
|
11589
|
+
setStoreOpen(answered.ok ? answered.data : null);
|
|
11590
|
+
})();
|
|
11591
|
+
return () => {
|
|
11592
|
+
alive = false;
|
|
11593
|
+
};
|
|
11594
|
+
}, [client]);
|
|
11595
|
+
return {
|
|
11596
|
+
storeOpen,
|
|
11597
|
+
blocked: storeOpen === false,
|
|
11598
|
+
why: storeOpen === false ? PUBLISH_NEEDS_THE_STORE_ON : null
|
|
11599
|
+
};
|
|
11600
|
+
}
|
|
11601
|
+
|
|
11602
|
+
// src/FormBuilder.tsx
|
|
11455
11603
|
import { publicFormPath } from "@ai-matrx/records";
|
|
11456
11604
|
import {
|
|
11457
11605
|
BasicInput as BasicInput13,
|
|
@@ -11464,7 +11612,7 @@ import {
|
|
|
11464
11612
|
} from "@ai-matrx/design-system";
|
|
11465
11613
|
|
|
11466
11614
|
// src/FormRunner.tsx
|
|
11467
|
-
import { useCallback as useCallback24, useEffect as
|
|
11615
|
+
import { useCallback as useCallback24, useEffect as useEffect27, useMemo as useMemo25, useRef as useRef11, useState as useState40 } from "react";
|
|
11468
11616
|
import { useFields as useFields17, useOptionalRecordsClient as useOptionalRecordsClient4 } from "@ai-matrx/records/react";
|
|
11469
11617
|
import { Button as Button36, Progress, Skeleton as Skeleton20, cn as cn36 } from "@ai-matrx/design-system";
|
|
11470
11618
|
import { Fragment as Fragment18, jsx as jsx42, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
@@ -11535,13 +11683,13 @@ function FormStage({
|
|
|
11535
11683
|
connected = false
|
|
11536
11684
|
}) {
|
|
11537
11685
|
const host = useRecordsUi();
|
|
11538
|
-
const [answers, setAnswers] =
|
|
11539
|
-
const [at, setAt] =
|
|
11540
|
-
const [error, setError] =
|
|
11541
|
-
const [refusal, setRefusal] =
|
|
11542
|
-
const [writing, setWriting] =
|
|
11543
|
-
const [done, setDone] =
|
|
11544
|
-
const [hidden, setHidden] =
|
|
11686
|
+
const [answers, setAnswers] = useState40({});
|
|
11687
|
+
const [at, setAt] = useState40(0);
|
|
11688
|
+
const [error, setError] = useState40(null);
|
|
11689
|
+
const [refusal, setRefusal] = useState40(null);
|
|
11690
|
+
const [writing, setWriting] = useState40(false);
|
|
11691
|
+
const [done, setDone] = useState40(null);
|
|
11692
|
+
const [hidden, setHidden] = useState40({});
|
|
11545
11693
|
const decoy = useRef11("");
|
|
11546
11694
|
const stage = useRef11(null);
|
|
11547
11695
|
const questions = useMemo25(() => {
|
|
@@ -11558,7 +11706,7 @@ function FormStage({
|
|
|
11558
11706
|
};
|
|
11559
11707
|
});
|
|
11560
11708
|
}, [fields, form.questions]);
|
|
11561
|
-
|
|
11709
|
+
useEffect27(() => {
|
|
11562
11710
|
let cancelled = false;
|
|
11563
11711
|
const conditional = questions.filter((q) => q.showIf);
|
|
11564
11712
|
if (conditional.length === 0 || !evaluate) return;
|
|
@@ -11629,7 +11777,7 @@ function FormStage({
|
|
|
11629
11777
|
if (event.shiftKey) retreat();
|
|
11630
11778
|
else advance();
|
|
11631
11779
|
}
|
|
11632
|
-
|
|
11780
|
+
useEffect27(() => {
|
|
11633
11781
|
const input = stage.current?.querySelector(
|
|
11634
11782
|
"input:not([tabindex='-1']), textarea, select, [role='combobox']"
|
|
11635
11783
|
);
|
|
@@ -11723,7 +11871,7 @@ function Question({
|
|
|
11723
11871
|
onChange,
|
|
11724
11872
|
upload
|
|
11725
11873
|
}) {
|
|
11726
|
-
const [uploadError, setUploadError] =
|
|
11874
|
+
const [uploadError, setUploadError] = useState40(null);
|
|
11727
11875
|
const field = question.field;
|
|
11728
11876
|
if (!field) return null;
|
|
11729
11877
|
const id = `form-${field.key}`;
|
|
@@ -11780,21 +11928,22 @@ function whyNotAskable(fields, hidden = []) {
|
|
|
11780
11928
|
// src/FormBuilder.tsx
|
|
11781
11929
|
import { Fragment as Fragment19, jsx as jsx43, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
11782
11930
|
function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
|
|
11783
|
-
const client =
|
|
11931
|
+
const client = useRecordsClient28();
|
|
11932
|
+
const publishGate = usePublishGate();
|
|
11784
11933
|
const host = useRecordsUi();
|
|
11785
11934
|
const claimSeed = useSeedGuard();
|
|
11786
11935
|
const table = useTable14(tableId);
|
|
11787
11936
|
const rights = useTableRights(table.data);
|
|
11788
11937
|
const fields = useFields18(tableId);
|
|
11789
|
-
const [forms, setForms] =
|
|
11790
|
-
const [error, setError] =
|
|
11791
|
-
const [activeId, setActiveId] =
|
|
11792
|
-
const [draft, setDraft] =
|
|
11793
|
-
const [saving, setSaving] =
|
|
11794
|
-
const [saved, setSaved] =
|
|
11795
|
-
const [publishing, setPublishing] =
|
|
11796
|
-
const [copied, setCopied] =
|
|
11797
|
-
const [shownUrl, setShownUrl] =
|
|
11938
|
+
const [forms, setForms] = useState41(null);
|
|
11939
|
+
const [error, setError] = useState41(null);
|
|
11940
|
+
const [activeId, setActiveId] = useState41(activeFormId ?? null);
|
|
11941
|
+
const [draft, setDraft] = useState41(null);
|
|
11942
|
+
const [saving, setSaving] = useState41(false);
|
|
11943
|
+
const [saved, setSaved] = useState41(null);
|
|
11944
|
+
const [publishing, setPublishing] = useState41(false);
|
|
11945
|
+
const [copied, setCopied] = useState41(false);
|
|
11946
|
+
const [shownUrl, setShownUrl] = useState41(null);
|
|
11798
11947
|
const publicOrigin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
|
|
11799
11948
|
const load = useCallback25(async () => {
|
|
11800
11949
|
const answered = await client.forms({ table_id: tableId });
|
|
@@ -11823,10 +11972,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
|
|
|
11823
11972
|
setError(null);
|
|
11824
11973
|
setForms(mine);
|
|
11825
11974
|
}, [client, tableId, seed, claimSeed]);
|
|
11826
|
-
|
|
11975
|
+
useEffect28(() => {
|
|
11827
11976
|
void load();
|
|
11828
11977
|
}, [load]);
|
|
11829
|
-
|
|
11978
|
+
useEffect28(() => {
|
|
11830
11979
|
if (!forms || forms.length === 0) return;
|
|
11831
11980
|
const chosen = forms.find((f) => f.id === (activeFormId ?? activeId)) ?? forms[0];
|
|
11832
11981
|
if (chosen.id !== activeId) setActiveId(chosen.id);
|
|
@@ -11937,8 +12086,8 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
|
|
|
11937
12086
|
{
|
|
11938
12087
|
url: `${publicOrigin}${publicFormPath(draft.id)}`,
|
|
11939
12088
|
state: draft.state,
|
|
11940
|
-
mayPublish: rights.structure,
|
|
11941
|
-
why: rights.why("structure"),
|
|
12089
|
+
mayPublish: rights.structure && !publishGate.blocked,
|
|
12090
|
+
why: publishGate.why ?? rights.why("structure"),
|
|
11942
12091
|
busy: publishing,
|
|
11943
12092
|
copied,
|
|
11944
12093
|
shownUrl,
|
|
@@ -12237,17 +12386,17 @@ function groupLabel(groups) {
|
|
|
12237
12386
|
|
|
12238
12387
|
// src/chartFrame.tsx
|
|
12239
12388
|
import {
|
|
12240
|
-
useEffect as
|
|
12389
|
+
useEffect as useEffect29,
|
|
12241
12390
|
useId as useId2,
|
|
12242
12391
|
useRef as useRef12,
|
|
12243
|
-
useState as
|
|
12392
|
+
useState as useState42
|
|
12244
12393
|
} from "react";
|
|
12245
12394
|
import { cn as cn38 } from "@ai-matrx/design-system";
|
|
12246
12395
|
import { jsx as jsx44, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
12247
12396
|
function useMeasuredWidth(fallback = 480) {
|
|
12248
12397
|
const ref = useRef12(null);
|
|
12249
|
-
const [width, setWidth] =
|
|
12250
|
-
|
|
12398
|
+
const [width, setWidth] = useState42(fallback);
|
|
12399
|
+
useEffect29(() => {
|
|
12251
12400
|
const node = ref.current;
|
|
12252
12401
|
if (!node) return;
|
|
12253
12402
|
const apply = () => {
|
|
@@ -12371,23 +12520,23 @@ function isSignatureField(field) {
|
|
|
12371
12520
|
}
|
|
12372
12521
|
|
|
12373
12522
|
// src/DocTemplate.tsx
|
|
12374
|
-
import { useCallback as useCallback26, useEffect as
|
|
12375
|
-
import { useFields as useFields19, useRecordsClient as
|
|
12523
|
+
import { useCallback as useCallback26, useEffect as useEffect30, useState as useState43 } from "react";
|
|
12524
|
+
import { useFields as useFields19, useRecordsClient as useRecordsClient29, useTable as useTable15 } from "@ai-matrx/records/react";
|
|
12376
12525
|
import { BasicInput as BasicInput14, BasicTextarea as BasicTextarea6, Button as Button38, Label as Label8, Skeleton as Skeleton22, cn as cn39 } from "@ai-matrx/design-system";
|
|
12377
12526
|
import { jsx as jsx45, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
12378
12527
|
function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, className }) {
|
|
12379
|
-
const client =
|
|
12528
|
+
const client = useRecordsClient29();
|
|
12380
12529
|
const claimSeed = useSeedGuard();
|
|
12381
12530
|
const table = useTable15(tableId);
|
|
12382
12531
|
const rights = useTableRights(table.data);
|
|
12383
12532
|
const fields = useFields19(tableId);
|
|
12384
|
-
const [templates, setTemplates] =
|
|
12385
|
-
const [error, setError] =
|
|
12386
|
-
const [activeId, setActiveId] =
|
|
12387
|
-
const [draftName, setDraftName] =
|
|
12388
|
-
const [draftBody, setDraftBody] =
|
|
12389
|
-
const [unresolved, setUnresolved] =
|
|
12390
|
-
const [saving, setSaving] =
|
|
12533
|
+
const [templates, setTemplates] = useState43(null);
|
|
12534
|
+
const [error, setError] = useState43(null);
|
|
12535
|
+
const [activeId, setActiveId] = useState43(activeTemplateId ?? null);
|
|
12536
|
+
const [draftName, setDraftName] = useState43("");
|
|
12537
|
+
const [draftBody, setDraftBody] = useState43("");
|
|
12538
|
+
const [unresolved, setUnresolved] = useState43([]);
|
|
12539
|
+
const [saving, setSaving] = useState43(false);
|
|
12391
12540
|
const load = useCallback26(async () => {
|
|
12392
12541
|
const held = await client.docTemplates({ table_id: tableId });
|
|
12393
12542
|
if (!held.ok) {
|
|
@@ -12419,10 +12568,10 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
|
|
|
12419
12568
|
setError(null);
|
|
12420
12569
|
setTemplates(rows);
|
|
12421
12570
|
}, [client, tableId, seed, fields.data]);
|
|
12422
|
-
|
|
12571
|
+
useEffect30(() => {
|
|
12423
12572
|
void load();
|
|
12424
12573
|
}, [load]);
|
|
12425
|
-
|
|
12574
|
+
useEffect30(() => {
|
|
12426
12575
|
if (!templates || templates.length === 0) return;
|
|
12427
12576
|
const chosen = templates.find((t) => t.id === (activeTemplateId ?? activeId)) ?? templates[0];
|
|
12428
12577
|
if (chosen.id !== activeId) setActiveId(chosen.id);
|
|
@@ -12430,7 +12579,7 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
|
|
|
12430
12579
|
setDraftBody(chosen.body);
|
|
12431
12580
|
onActiveTemplate?.(chosen);
|
|
12432
12581
|
}, [templates, activeTemplateId]);
|
|
12433
|
-
|
|
12582
|
+
useEffect30(() => {
|
|
12434
12583
|
let cancelled = false;
|
|
12435
12584
|
if (draftBody.trim() === "") {
|
|
12436
12585
|
setUnresolved([]);
|
|
@@ -12550,17 +12699,17 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
|
|
|
12550
12699
|
}
|
|
12551
12700
|
|
|
12552
12701
|
// src/DocRender.tsx
|
|
12553
|
-
import { useCallback as useCallback27, useEffect as
|
|
12554
|
-
import { useRecordsClient as
|
|
12702
|
+
import { useCallback as useCallback27, useEffect as useEffect31, useRef as useRef13, useState as useState44 } from "react";
|
|
12703
|
+
import { useRecordsClient as useRecordsClient30 } from "@ai-matrx/records/react";
|
|
12555
12704
|
import { Button as Button39, Skeleton as Skeleton23, cn as cn40 } from "@ai-matrx/design-system";
|
|
12556
12705
|
import { jsx as jsx46, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
12557
12706
|
function DocRender({ templateId, recordId, filename, onRendered, className }) {
|
|
12558
|
-
const client =
|
|
12559
|
-
const [preview, setPreview] =
|
|
12560
|
-
const [renders, setRenders] =
|
|
12561
|
-
const [showing, setShowing] =
|
|
12562
|
-
const [error, setError] =
|
|
12563
|
-
const [busy, setBusy] =
|
|
12707
|
+
const client = useRecordsClient30();
|
|
12708
|
+
const [preview, setPreview] = useState44(null);
|
|
12709
|
+
const [renders, setRenders] = useState44(null);
|
|
12710
|
+
const [showing, setShowing] = useState44(null);
|
|
12711
|
+
const [error, setError] = useState44(null);
|
|
12712
|
+
const [busy, setBusy] = useState44(null);
|
|
12564
12713
|
const paper = useRef13(null);
|
|
12565
12714
|
const load = useCallback27(async () => {
|
|
12566
12715
|
const [body, held] = await Promise.all([
|
|
@@ -12579,7 +12728,7 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
|
|
|
12579
12728
|
setPreview(body.data);
|
|
12580
12729
|
setRenders(held.data.filter((r) => r.template_id === templateId));
|
|
12581
12730
|
}, [client, templateId, recordId]);
|
|
12582
|
-
|
|
12731
|
+
useEffect31(() => {
|
|
12583
12732
|
void load();
|
|
12584
12733
|
}, [load]);
|
|
12585
12734
|
async function freeze() {
|
|
@@ -12663,21 +12812,21 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
|
|
|
12663
12812
|
}
|
|
12664
12813
|
|
|
12665
12814
|
// src/SignBlock.tsx
|
|
12666
|
-
import { useCallback as useCallback28, useEffect as
|
|
12667
|
-
import { useFields as useFields20, useRecordsClient as
|
|
12815
|
+
import { useCallback as useCallback28, useEffect as useEffect32, useState as useState45 } from "react";
|
|
12816
|
+
import { useFields as useFields20, useRecordsClient as useRecordsClient31 } from "@ai-matrx/records/react";
|
|
12668
12817
|
import { BasicInput as BasicInput15, Button as Button40, Skeleton as Skeleton24, cn as cn41 } from "@ai-matrx/design-system";
|
|
12669
12818
|
import { useTable as useTable16 } from "@ai-matrx/records/react";
|
|
12670
12819
|
import { jsx as jsx47, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
12671
12820
|
function SignBlock({ tableId, recordId, render, className }) {
|
|
12672
|
-
const client =
|
|
12821
|
+
const client = useRecordsClient31();
|
|
12673
12822
|
const table = useTable16(tableId);
|
|
12674
12823
|
const rights = useTableRights(table.data);
|
|
12675
12824
|
const fields = useFields20(tableId);
|
|
12676
|
-
const [signatures, setSignatures] =
|
|
12677
|
-
const [verdicts, setVerdicts] =
|
|
12678
|
-
const [error, setError] =
|
|
12679
|
-
const [name, setName] =
|
|
12680
|
-
const [busy, setBusy] =
|
|
12825
|
+
const [signatures, setSignatures] = useState45(null);
|
|
12826
|
+
const [verdicts, setVerdicts] = useState45({});
|
|
12827
|
+
const [error, setError] = useState45(null);
|
|
12828
|
+
const [name, setName] = useState45("");
|
|
12829
|
+
const [busy, setBusy] = useState45(false);
|
|
12681
12830
|
const load = useCallback28(async () => {
|
|
12682
12831
|
const held = await client.docSignatures({ record_id: recordId });
|
|
12683
12832
|
if (!held.ok) {
|
|
@@ -12693,7 +12842,7 @@ function SignBlock({ tableId, recordId, render, className }) {
|
|
|
12693
12842
|
}
|
|
12694
12843
|
setVerdicts(answers);
|
|
12695
12844
|
}, [client, recordId]);
|
|
12696
|
-
|
|
12845
|
+
useEffect32(() => {
|
|
12697
12846
|
void load();
|
|
12698
12847
|
}, [load]);
|
|
12699
12848
|
async function sign(field) {
|
|
@@ -12800,22 +12949,22 @@ function SignBlock({ tableId, recordId, render, className }) {
|
|
|
12800
12949
|
}
|
|
12801
12950
|
|
|
12802
12951
|
// src/NotifyRuleEditor.tsx
|
|
12803
|
-
import { useCallback as useCallback29, useEffect as
|
|
12804
|
-
import { useRecordsClient as
|
|
12952
|
+
import { useCallback as useCallback29, useEffect as useEffect33, useState as useState46 } from "react";
|
|
12953
|
+
import { useRecordsClient as useRecordsClient32, useTable as useTable17 } from "@ai-matrx/records/react";
|
|
12805
12954
|
import { Button as Button41, Skeleton as Skeleton25, cn as cn42 } from "@ai-matrx/design-system";
|
|
12806
12955
|
import { jsx as jsx48, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
12807
12956
|
var CADENCE_WORDS2 = SUBSCRIPTION_CADENCE_LABEL;
|
|
12808
12957
|
var CHANNEL_WORDS3 = SUBSCRIPTION_CHANNEL_LABEL;
|
|
12809
12958
|
function NotifyRuleEditor({ tableId, seed, className }) {
|
|
12810
|
-
const client =
|
|
12959
|
+
const client = useRecordsClient32();
|
|
12811
12960
|
const host = useRecordsUi();
|
|
12812
12961
|
const table = useTable17(tableId);
|
|
12813
12962
|
const rights = useTableRights(table.data);
|
|
12814
|
-
const [subscriptions, setSubscriptions] =
|
|
12815
|
-
const [cadences, setCadences] =
|
|
12816
|
-
const [views, setViews] =
|
|
12817
|
-
const [error, setError] =
|
|
12818
|
-
const [busy, setBusy] =
|
|
12963
|
+
const [subscriptions, setSubscriptions] = useState46(null);
|
|
12964
|
+
const [cadences, setCadences] = useState46([]);
|
|
12965
|
+
const [views, setViews] = useState46(null);
|
|
12966
|
+
const [error, setError] = useState46(null);
|
|
12967
|
+
const [busy, setBusy] = useState46(false);
|
|
12819
12968
|
const load = useCallback29(async () => {
|
|
12820
12969
|
const [held, offered] = await Promise.all([
|
|
12821
12970
|
// THE PERSON'S OWN DOOR, not the notifier's. It answers what is addressed
|
|
@@ -12836,7 +12985,7 @@ function NotifyRuleEditor({ tableId, seed, className }) {
|
|
|
12836
12985
|
if (host.savedViews) setViews(await host.savedViews());
|
|
12837
12986
|
else setViews(null);
|
|
12838
12987
|
}, [client, host, tableId]);
|
|
12839
|
-
|
|
12988
|
+
useEffect33(() => {
|
|
12840
12989
|
void load();
|
|
12841
12990
|
}, [load]);
|
|
12842
12991
|
const write = useCallback29(
|
|
@@ -12864,7 +13013,7 @@ function NotifyRuleEditor({ tableId, seed, className }) {
|
|
|
12864
13013
|
},
|
|
12865
13014
|
[client, tableId]
|
|
12866
13015
|
);
|
|
12867
|
-
|
|
13016
|
+
useEffect33(() => {
|
|
12868
13017
|
if (!subscriptions || !seed || seed.length === 0) return;
|
|
12869
13018
|
const missing = seed.filter((s) => !subscriptions.some((held) => held.name === s.name));
|
|
12870
13019
|
if (missing.length === 0) return;
|
|
@@ -13320,24 +13469,34 @@ function Drawing({
|
|
|
13320
13469
|
}
|
|
13321
13470
|
|
|
13322
13471
|
// src/DashboardCanvas.tsx
|
|
13323
|
-
import { useCallback as useCallback30, useEffect as
|
|
13324
|
-
import { useFields as useFields21, useRecordsClient as
|
|
13325
|
-
import {
|
|
13472
|
+
import { useCallback as useCallback30, useEffect as useEffect34, useMemo as useMemo28, useState as useState47 } from "react";
|
|
13473
|
+
import { useFields as useFields21, useRecordsClient as useRecordsClient33, useTable as useTable18 } from "@ai-matrx/records/react";
|
|
13474
|
+
import {
|
|
13475
|
+
BasicInput as BasicInput16,
|
|
13476
|
+
Button as Button42,
|
|
13477
|
+
Select as Select5,
|
|
13478
|
+
SelectContent as SelectContent5,
|
|
13479
|
+
SelectItem as SelectItem5,
|
|
13480
|
+
SelectTrigger as SelectTrigger5,
|
|
13481
|
+
SelectValue as SelectValue5,
|
|
13482
|
+
Skeleton as Skeleton26,
|
|
13483
|
+
cn as cn44
|
|
13484
|
+
} from "@ai-matrx/design-system";
|
|
13326
13485
|
import { Fragment as Fragment21, jsx as jsx50, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
13327
13486
|
function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
|
|
13328
|
-
const client =
|
|
13487
|
+
const client = useRecordsClient33();
|
|
13329
13488
|
const host = useRecordsUi();
|
|
13330
13489
|
const table = useTable18(tableId);
|
|
13331
13490
|
const rights = useTableRights(table.data);
|
|
13332
13491
|
const fields = useFields21(tableId);
|
|
13333
|
-
const [boards, setBoards] =
|
|
13334
|
-
const [error, setError] =
|
|
13335
|
-
const [activeId, setActiveId] =
|
|
13336
|
-
const [run, setRun] =
|
|
13337
|
-
const [running, setRunning] =
|
|
13338
|
-
const [question, setQuestion] =
|
|
13339
|
-
const [asking, setAsking] =
|
|
13340
|
-
const [scheduling, setScheduling] =
|
|
13492
|
+
const [boards, setBoards] = useState47(null);
|
|
13493
|
+
const [error, setError] = useState47(null);
|
|
13494
|
+
const [activeId, setActiveId] = useState47(activeDashboardId ?? null);
|
|
13495
|
+
const [run, setRun] = useState47(null);
|
|
13496
|
+
const [running, setRunning] = useState47(false);
|
|
13497
|
+
const [question, setQuestion] = useState47("");
|
|
13498
|
+
const [asking, setAsking] = useState47(false);
|
|
13499
|
+
const [scheduling, setScheduling] = useState47(false);
|
|
13341
13500
|
const load = useCallback30(async () => {
|
|
13342
13501
|
const answered = await client.dashboards({ table_id: tableId });
|
|
13343
13502
|
if (!answered.ok) {
|
|
@@ -13347,17 +13506,17 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
|
|
|
13347
13506
|
setError(null);
|
|
13348
13507
|
setBoards(answered.data.map(dashboardFromSummary));
|
|
13349
13508
|
}, [client, tableId]);
|
|
13350
|
-
|
|
13509
|
+
useEffect34(() => {
|
|
13351
13510
|
void load();
|
|
13352
13511
|
}, [load]);
|
|
13353
|
-
|
|
13512
|
+
useEffect34(() => {
|
|
13354
13513
|
if (!boards || boards.length === 0) return;
|
|
13355
13514
|
const chosen = boards.find((d) => d.id === (activeDashboardId ?? activeId)) ?? boards[0];
|
|
13356
13515
|
if (chosen.id !== activeId) setActiveId(chosen.id);
|
|
13357
13516
|
}, [boards, activeDashboardId]);
|
|
13358
13517
|
const board = useMemo28(() => boards?.find((d) => d.id === activeId) ?? null, [boards, activeId]);
|
|
13359
13518
|
const filterKey = JSON.stringify(filter ?? {});
|
|
13360
|
-
|
|
13519
|
+
useEffect34(() => {
|
|
13361
13520
|
if (!activeId) {
|
|
13362
13521
|
setRun(null);
|
|
13363
13522
|
return;
|
|
@@ -13396,8 +13555,8 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
|
|
|
13396
13555
|
[client, tableId, load, filter]
|
|
13397
13556
|
);
|
|
13398
13557
|
async function create() {
|
|
13399
|
-
const
|
|
13400
|
-
const byField =
|
|
13558
|
+
const all = fields.data ?? [];
|
|
13559
|
+
const byField = offerableFields(all, "choice")[0] ?? all.find((f) => f.type === "text" || f.type === "list");
|
|
13401
13560
|
const by = byField?.key;
|
|
13402
13561
|
await declare2(
|
|
13403
13562
|
{
|
|
@@ -13568,6 +13727,32 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
|
|
|
13568
13727
|
children: CHART_KINDS.map((kind) => /* @__PURE__ */ jsx50("option", { value: kind, children: CHART_KIND_LABEL[kind] }, kind))
|
|
13569
13728
|
}
|
|
13570
13729
|
),
|
|
13730
|
+
(board.blocks[index].groupBy ?? []).length > 0 ? /* @__PURE__ */ jsx50(
|
|
13731
|
+
GroupingPicker,
|
|
13732
|
+
{
|
|
13733
|
+
block: board.blocks[index],
|
|
13734
|
+
fields: fields.data ?? [],
|
|
13735
|
+
onPick: (key) => void declare2(
|
|
13736
|
+
board,
|
|
13737
|
+
board.blocks.map((b, i) => {
|
|
13738
|
+
if (i !== index) return b;
|
|
13739
|
+
const picked = (fields.data ?? []).find((f) => f.key === key);
|
|
13740
|
+
const wasNamedAfterItsColumn = (fields.data ?? []).some(
|
|
13741
|
+
(f) => b.title === `By ${fieldName(f)}`
|
|
13742
|
+
);
|
|
13743
|
+
return {
|
|
13744
|
+
...b,
|
|
13745
|
+
groupBy: [key],
|
|
13746
|
+
// A block titled after the column it grouped by
|
|
13747
|
+
// must not keep saying "By Job Number" once it
|
|
13748
|
+
// groups by Status. A title somebody wrote
|
|
13749
|
+
// themselves is left alone.
|
|
13750
|
+
...wasNamedAfterItsColumn && picked ? { title: `By ${fieldName(picked)}` } : {}
|
|
13751
|
+
};
|
|
13752
|
+
})
|
|
13753
|
+
)
|
|
13754
|
+
}
|
|
13755
|
+
) : null,
|
|
13571
13756
|
/* @__PURE__ */ jsx50(
|
|
13572
13757
|
Button42,
|
|
13573
13758
|
{
|
|
@@ -13586,10 +13771,49 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
|
|
|
13586
13771
|
] })
|
|
13587
13772
|
] });
|
|
13588
13773
|
}
|
|
13774
|
+
function groupingChoices(all) {
|
|
13775
|
+
const once = [];
|
|
13776
|
+
for (const field of all) if (!once.some((f) => f.key === field.key)) once.push(field);
|
|
13777
|
+
const sensible = offerableFields(once, "choice");
|
|
13778
|
+
const isSensible = (field) => sensible.some((s) => s.key === field.key);
|
|
13779
|
+
return [
|
|
13780
|
+
...sensible.map((field) => ({ field, unusual: false })),
|
|
13781
|
+
...once.filter((field) => !isSensible(field)).map((field) => ({ field, unusual: true }))
|
|
13782
|
+
];
|
|
13783
|
+
}
|
|
13784
|
+
function GroupingPicker({
|
|
13785
|
+
block,
|
|
13786
|
+
fields,
|
|
13787
|
+
onPick
|
|
13788
|
+
}) {
|
|
13789
|
+
const choices = groupingChoices(fields);
|
|
13790
|
+
const current = block.groupBy?.[0] ?? "";
|
|
13791
|
+
if (choices.length === 0) {
|
|
13792
|
+
return /* @__PURE__ */ jsx50("span", { className: "text-muted-foreground", children: "This table has no columns yet, so there is nothing to group this block by." });
|
|
13793
|
+
}
|
|
13794
|
+
const known = choices.some((c) => c.field.key === current);
|
|
13795
|
+
return /* @__PURE__ */ jsxs46(Fragment21, { children: [
|
|
13796
|
+
/* @__PURE__ */ jsx50("label", { className: "text-muted-foreground", htmlFor: `block-group-${block.title}`, children: "Group by" }),
|
|
13797
|
+
/* @__PURE__ */ jsxs46(Select5, { value: known ? current : "", onValueChange: onPick, children: [
|
|
13798
|
+
/* @__PURE__ */ jsx50(
|
|
13799
|
+
SelectTrigger5,
|
|
13800
|
+
{
|
|
13801
|
+
size: "sm",
|
|
13802
|
+
id: `block-group-${block.title}`,
|
|
13803
|
+
"aria-label": `Which column ${block.title} is grouped by`,
|
|
13804
|
+
className: "h-7 min-w-[10rem] text-xs",
|
|
13805
|
+
children: /* @__PURE__ */ jsx50(SelectValue5, { placeholder: "Choose a column" })
|
|
13806
|
+
}
|
|
13807
|
+
),
|
|
13808
|
+
/* @__PURE__ */ jsx50(SelectContent5, { children: choices.map(({ field, unusual }) => /* @__PURE__ */ jsx50(SelectItem5, { value: field.key, children: unusual ? `${fieldName(field)} \u2014 ${UNUSUAL_FIELD_NOTE}` : fieldName(field) }, field.key)) })
|
|
13809
|
+
] }),
|
|
13810
|
+
known ? null : /* @__PURE__ */ jsx50("span", { className: "text-muted-foreground", children: "The column this block was grouped by is no longer on this table \u2014 choose another." })
|
|
13811
|
+
] });
|
|
13812
|
+
}
|
|
13589
13813
|
|
|
13590
13814
|
// src/FormsPanel.tsx
|
|
13591
|
-
import { useCallback as useCallback31, useEffect as
|
|
13592
|
-
import { useRecordsClient as
|
|
13815
|
+
import { useCallback as useCallback31, useEffect as useEffect35, useState as useState48 } from "react";
|
|
13816
|
+
import { useRecordsClient as useRecordsClient34, useTable as useTable19 } from "@ai-matrx/records/react";
|
|
13593
13817
|
import { publicFormPath as publicFormPath2 } from "@ai-matrx/records";
|
|
13594
13818
|
import { Badge as Badge15, Button as Button43, Skeleton as Skeleton27, cn as cn45 } from "@ai-matrx/design-system";
|
|
13595
13819
|
import { Fragment as Fragment22, jsx as jsx51, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
@@ -13600,15 +13824,16 @@ function formSuggestion(tableName2) {
|
|
|
13600
13824
|
return `Make me a form that collects new ${subject} entries and tells me when somebody answers.`;
|
|
13601
13825
|
}
|
|
13602
13826
|
function FormsPanel({ tableId, className }) {
|
|
13603
|
-
const client =
|
|
13827
|
+
const client = useRecordsClient34();
|
|
13828
|
+
const publishGate = usePublishGate();
|
|
13604
13829
|
const host = useRecordsUi();
|
|
13605
13830
|
const table = useTable19(tableId);
|
|
13606
13831
|
const rights = useTableRights(table.data);
|
|
13607
|
-
const [forms, setForms] =
|
|
13608
|
-
const [error, setError] =
|
|
13609
|
-
const [busy, setBusy] =
|
|
13610
|
-
const [copied, setCopied] =
|
|
13611
|
-
const [building, setBuilding] =
|
|
13832
|
+
const [forms, setForms] = useState48(null);
|
|
13833
|
+
const [error, setError] = useState48(null);
|
|
13834
|
+
const [busy, setBusy] = useState48(null);
|
|
13835
|
+
const [copied, setCopied] = useState48(null);
|
|
13836
|
+
const [building, setBuilding] = useState48(false);
|
|
13612
13837
|
const load = useCallback31(async () => {
|
|
13613
13838
|
const answered = await client.forms({ table_id: tableId });
|
|
13614
13839
|
if (!answered.ok) {
|
|
@@ -13619,7 +13844,7 @@ function FormsPanel({ tableId, className }) {
|
|
|
13619
13844
|
setError(null);
|
|
13620
13845
|
setForms(answered.data);
|
|
13621
13846
|
}, [client, tableId]);
|
|
13622
|
-
|
|
13847
|
+
useEffect35(() => {
|
|
13623
13848
|
void load();
|
|
13624
13849
|
}, [load]);
|
|
13625
13850
|
const toggle = useCallback31(
|
|
@@ -13636,7 +13861,7 @@ function FormsPanel({ tableId, className }) {
|
|
|
13636
13861
|
},
|
|
13637
13862
|
[client, load]
|
|
13638
13863
|
);
|
|
13639
|
-
const [shown, setShown] =
|
|
13864
|
+
const [shown, setShown] = useState48(null);
|
|
13640
13865
|
const copy = useCallback31(async (url, formId) => {
|
|
13641
13866
|
try {
|
|
13642
13867
|
await navigator.clipboard.writeText(url);
|
|
@@ -13712,7 +13937,7 @@ function FormsPanel({ tableId, className }) {
|
|
|
13712
13937
|
] }),
|
|
13713
13938
|
/* @__PURE__ */ jsxs47("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
|
|
13714
13939
|
form.published_at ? /* @__PURE__ */ jsx51(Button43, { size: "sm", variant: "outline", onClick: () => void copy(url, form.form_id), children: copied === form.form_id ? "Copied" : "Copy link" }) : null,
|
|
13715
|
-
rights.structure ? /* @__PURE__ */ jsx51(
|
|
13940
|
+
rights.structure && !publishGate.blocked ? /* @__PURE__ */ jsx51(
|
|
13716
13941
|
Button43,
|
|
13717
13942
|
{
|
|
13718
13943
|
size: "sm",
|
|
@@ -13723,6 +13948,7 @@ function FormsPanel({ tableId, className }) {
|
|
|
13723
13948
|
}
|
|
13724
13949
|
) : null
|
|
13725
13950
|
] }),
|
|
13951
|
+
rights.structure && publishGate.why ? /* @__PURE__ */ jsx51("p", { className: "mt-1.5 text-xs text-muted-foreground", children: publishGate.why }) : null,
|
|
13726
13952
|
shown && shown === url ? /* @__PURE__ */ jsxs47("p", { className: "mt-1.5 break-all rounded border border-dashed px-2 py-1 text-xs", children: [
|
|
13727
13953
|
"This browser would not let the page copy for you, so here it is to copy by hand:",
|
|
13728
13954
|
" ",
|
|
@@ -13735,8 +13961,8 @@ function FormsPanel({ tableId, className }) {
|
|
|
13735
13961
|
}
|
|
13736
13962
|
|
|
13737
13963
|
// src/BookingBuilder.tsx
|
|
13738
|
-
import { useCallback as useCallback32, useEffect as
|
|
13739
|
-
import { useFields as useFields22, useRecordsClient as
|
|
13964
|
+
import { useCallback as useCallback32, useEffect as useEffect36, useMemo as useMemo29, useState as useState49 } from "react";
|
|
13965
|
+
import { useFields as useFields22, useRecordsClient as useRecordsClient35, useTable as useTable20 } from "@ai-matrx/records/react";
|
|
13740
13966
|
import {
|
|
13741
13967
|
bookingPath
|
|
13742
13968
|
} from "@ai-matrx/records";
|
|
@@ -13766,28 +13992,29 @@ function draftWindows(availability) {
|
|
|
13766
13992
|
});
|
|
13767
13993
|
}
|
|
13768
13994
|
function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
|
|
13769
|
-
const client =
|
|
13995
|
+
const client = useRecordsClient35();
|
|
13996
|
+
const publishGate = usePublishGate();
|
|
13770
13997
|
const host = useRecordsUi();
|
|
13771
13998
|
const table = useTable20(tableId);
|
|
13772
13999
|
const rights = useTableRights(table.data);
|
|
13773
14000
|
const fields = useFields22(tableId);
|
|
13774
|
-
const [existing, setExisting] =
|
|
13775
|
-
const [loaded, setLoaded] =
|
|
13776
|
-
const [error, setError] =
|
|
13777
|
-
const [saving, setSaving] =
|
|
13778
|
-
const [publishing, setPublishing] =
|
|
13779
|
-
const [copied, setCopied] =
|
|
13780
|
-
const [title, setTitle] =
|
|
13781
|
-
const [minutes, setMinutes] =
|
|
13782
|
-
const [buffer, setBuffer] =
|
|
13783
|
-
const [lead, setLead] =
|
|
13784
|
-
const [perDay, setPerDay] =
|
|
13785
|
-
const [days, setDays] =
|
|
13786
|
-
const [windows, setWindows] =
|
|
13787
|
-
const [asked, setAsked] =
|
|
13788
|
-
const [confirmation, setConfirmation] =
|
|
13789
|
-
const [offer, setOffer] =
|
|
13790
|
-
const [formId, setFormId] =
|
|
14001
|
+
const [existing, setExisting] = useState49(null);
|
|
14002
|
+
const [loaded, setLoaded] = useState49(false);
|
|
14003
|
+
const [error, setError] = useState49(null);
|
|
14004
|
+
const [saving, setSaving] = useState49(false);
|
|
14005
|
+
const [publishing, setPublishing] = useState49(false);
|
|
14006
|
+
const [copied, setCopied] = useState49(false);
|
|
14007
|
+
const [title, setTitle] = useState49("");
|
|
14008
|
+
const [minutes, setMinutes] = useState49(30);
|
|
14009
|
+
const [buffer, setBuffer] = useState49(0);
|
|
14010
|
+
const [lead, setLead] = useState49(120);
|
|
14011
|
+
const [perDay, setPerDay] = useState49(8);
|
|
14012
|
+
const [days, setDays] = useState49(30);
|
|
14013
|
+
const [windows, setWindows] = useState49(() => draftWindows(null));
|
|
14014
|
+
const [asked, setAsked] = useState49([]);
|
|
14015
|
+
const [confirmation, setConfirmation] = useState49("");
|
|
14016
|
+
const [offer, setOffer] = useState49(null);
|
|
14017
|
+
const [formId, setFormId] = useState49(bookingId ?? null);
|
|
13791
14018
|
const publicOrigin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
|
|
13792
14019
|
const askable = useMemo29(
|
|
13793
14020
|
() => askableFields(fields.data ?? [], STORE_ANSWERS_THESE),
|
|
@@ -13809,18 +14036,18 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
|
|
|
13809
14036
|
setLoaded(true);
|
|
13810
14037
|
if (mine) setFormId(mine.form_id);
|
|
13811
14038
|
}, [client, tableId, bookingId]);
|
|
13812
|
-
|
|
14039
|
+
useEffect36(() => {
|
|
13813
14040
|
void load();
|
|
13814
14041
|
}, [load]);
|
|
13815
|
-
|
|
14042
|
+
useEffect36(() => {
|
|
13816
14043
|
if (title !== "" || !table.data) return;
|
|
13817
14044
|
setTitle(existing?.title ?? `Book a ${minutes}-minute ${table.data.name} appointment`);
|
|
13818
14045
|
}, [table.data, existing]);
|
|
13819
|
-
|
|
14046
|
+
useEffect36(() => {
|
|
13820
14047
|
if (!existing) return;
|
|
13821
14048
|
setMinutes(existing.slot_minutes);
|
|
13822
14049
|
}, [existing]);
|
|
13823
|
-
|
|
14050
|
+
useEffect36(() => {
|
|
13824
14051
|
if (!offer) return;
|
|
13825
14052
|
setWindows(draftWindows(offer));
|
|
13826
14053
|
setMinutes(offer.slot_minutes);
|
|
@@ -14066,7 +14293,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
|
|
|
14066
14293
|
children: copied ? "Copied" : "Copy link"
|
|
14067
14294
|
}
|
|
14068
14295
|
),
|
|
14069
|
-
/* @__PURE__ */ jsx52(
|
|
14296
|
+
publishGate.blocked ? null : /* @__PURE__ */ jsx52(
|
|
14070
14297
|
Button44,
|
|
14071
14298
|
{
|
|
14072
14299
|
size: "sm",
|
|
@@ -14075,15 +14302,15 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
|
|
|
14075
14302
|
children: publishing ? "\u2026" : existing?.published_at && !existing.closed_at ? "Unpublish" : "Publish"
|
|
14076
14303
|
}
|
|
14077
14304
|
),
|
|
14078
|
-
/* @__PURE__ */ jsx52("p", { className: "w-full text-xs text-muted-foreground", children: existing?.published_at && !existing.closed_at ? "Open. Anyone with this link can book a time." : "Not open yet \u2014 the link does not take bookings until you publish it." })
|
|
14305
|
+
/* @__PURE__ */ jsx52("p", { className: "w-full text-xs text-muted-foreground", children: publishGate.why ?? (existing?.published_at && !existing.closed_at ? "Open. Anyone with this link can book a time." : "Not open yet \u2014 the link does not take bookings until you publish it.") })
|
|
14079
14306
|
] }) : null
|
|
14080
14307
|
] })
|
|
14081
14308
|
);
|
|
14082
14309
|
}
|
|
14083
14310
|
|
|
14084
14311
|
// src/BookingSlots.tsx
|
|
14085
|
-
import { useCallback as useCallback33, useEffect as
|
|
14086
|
-
import { useRecordsClient as
|
|
14312
|
+
import { useCallback as useCallback33, useEffect as useEffect37, useMemo as useMemo30, useState as useState50 } from "react";
|
|
14313
|
+
import { useRecordsClient as useRecordsClient36, useMyLevels as useMyLevels2 } from "@ai-matrx/records/react";
|
|
14087
14314
|
import { bookingPath as bookingPath2 } from "@ai-matrx/records";
|
|
14088
14315
|
import { Badge as Badge16, Button as Button45, Skeleton as Skeleton29, cn as cn47 } from "@ai-matrx/design-system";
|
|
14089
14316
|
import { Fragment as Fragment24, jsx as jsx53, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
@@ -14095,14 +14322,14 @@ function bookingSuggestion(tableName2) {
|
|
|
14095
14322
|
var NO_ADMIN2 = "Opening a booking page lets people with no account take time in your calendar, so it needs the admin level on the table the appointments land in.";
|
|
14096
14323
|
var STATE_WORDS = BOOKING_PAGE_STATE_LABEL;
|
|
14097
14324
|
function BookingSlots({ tableId, className }) {
|
|
14098
|
-
const client =
|
|
14325
|
+
const client = useRecordsClient36();
|
|
14099
14326
|
const host = useRecordsUi();
|
|
14100
|
-
const [pages, setPages] =
|
|
14101
|
-
const [error, setError] =
|
|
14102
|
-
const [busy, setBusy] =
|
|
14103
|
-
const [copied, setCopied] =
|
|
14104
|
-
const [shown, setShown] =
|
|
14105
|
-
const [building, setBuilding] =
|
|
14327
|
+
const [pages, setPages] = useState50(null);
|
|
14328
|
+
const [error, setError] = useState50(null);
|
|
14329
|
+
const [busy, setBusy] = useState50(null);
|
|
14330
|
+
const [copied, setCopied] = useState50(null);
|
|
14331
|
+
const [shown, setShown] = useState50(null);
|
|
14332
|
+
const [building, setBuilding] = useState50(false);
|
|
14106
14333
|
const load = useCallback33(async () => {
|
|
14107
14334
|
const answered = await client.bookings(tableId ? { table_id: tableId } : {});
|
|
14108
14335
|
if (!answered.ok) {
|
|
@@ -14113,7 +14340,7 @@ function BookingSlots({ tableId, className }) {
|
|
|
14113
14340
|
setError(null);
|
|
14114
14341
|
setPages(answered.data);
|
|
14115
14342
|
}, [client, tableId]);
|
|
14116
|
-
|
|
14343
|
+
useEffect37(() => {
|
|
14117
14344
|
void load();
|
|
14118
14345
|
}, [load]);
|
|
14119
14346
|
const subjectIds = useMemo30(
|
|
@@ -14282,18 +14509,18 @@ function nextInWords(page) {
|
|
|
14282
14509
|
}
|
|
14283
14510
|
|
|
14284
14511
|
// src/CaptureSheet.tsx
|
|
14285
|
-
import { useCallback as useCallback35, useEffect as
|
|
14286
|
-
import { useFields as useFields23, useRecordsClient as
|
|
14512
|
+
import { useCallback as useCallback35, useEffect as useEffect39, useRef as useRef15, useState as useState52 } from "react";
|
|
14513
|
+
import { useFields as useFields23, useRecordsClient as useRecordsClient38, useTable as useTable21 } from "@ai-matrx/records/react";
|
|
14287
14514
|
import { Button as Button47, Input as Input4, Skeleton as Skeleton31, Textarea as Textarea3, cn as cn49 } from "@ai-matrx/design-system";
|
|
14288
14515
|
|
|
14289
14516
|
// src/CaptureRun.tsx
|
|
14290
|
-
import { useCallback as useCallback34, useEffect as
|
|
14517
|
+
import { useCallback as useCallback34, useEffect as useEffect38, useMemo as useMemo31, useRef as useRef14, useState as useState51 } from "react";
|
|
14291
14518
|
import {
|
|
14292
14519
|
coerceTypedAnswer as coerceTypedAnswer2,
|
|
14293
14520
|
coercionLabel,
|
|
14294
14521
|
openCaptureQueue
|
|
14295
14522
|
} from "@ai-matrx/records";
|
|
14296
|
-
import { useRecordsClient as
|
|
14523
|
+
import { useRecordsClient as useRecordsClient37 } from "@ai-matrx/records/react";
|
|
14297
14524
|
import { Button as Button46, Input as Input3, Skeleton as Skeleton30, Textarea as Textarea2, cn as cn48 } from "@ai-matrx/design-system";
|
|
14298
14525
|
import { jsx as jsx54, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
14299
14526
|
function controlFor(field) {
|
|
@@ -14332,21 +14559,21 @@ function whereWeAre(timeoutMs = 4e3) {
|
|
|
14332
14559
|
});
|
|
14333
14560
|
}
|
|
14334
14561
|
function CaptureRun({ sheetId, face: given, className }) {
|
|
14335
|
-
const client =
|
|
14562
|
+
const client = useRecordsClient37();
|
|
14336
14563
|
const host = useRecordsUi();
|
|
14337
|
-
const [face, setFace] =
|
|
14338
|
-
const [loadFailed, setLoadFailed] =
|
|
14339
|
-
const [at, setAt] =
|
|
14340
|
-
const [answers, setAnswers] =
|
|
14341
|
-
const [files, setFiles] =
|
|
14342
|
-
const [missing, setMissing] =
|
|
14343
|
-
const [done, setDone] =
|
|
14344
|
-
const [counts, setCounts] =
|
|
14345
|
-
const [items, setItems] =
|
|
14346
|
-
const [lastSynced, setLastSynced] =
|
|
14347
|
-
const [sending, setSending] =
|
|
14564
|
+
const [face, setFace] = useState51(given);
|
|
14565
|
+
const [loadFailed, setLoadFailed] = useState51(null);
|
|
14566
|
+
const [at, setAt] = useState51(0);
|
|
14567
|
+
const [answers, setAnswers] = useState51({});
|
|
14568
|
+
const [files, setFiles] = useState51({});
|
|
14569
|
+
const [missing, setMissing] = useState51(null);
|
|
14570
|
+
const [done, setDone] = useState51(null);
|
|
14571
|
+
const [counts, setCounts] = useState51({ waiting: 0, sending: 0, refused: 0, landed: 0 });
|
|
14572
|
+
const [items, setItems] = useState51([]);
|
|
14573
|
+
const [lastSynced, setLastSynced] = useState51(null);
|
|
14574
|
+
const [sending, setSending] = useState51(false);
|
|
14348
14575
|
const queueRef = useRef14(null);
|
|
14349
|
-
|
|
14576
|
+
useEffect38(() => {
|
|
14350
14577
|
const q2 = openCaptureQueue({
|
|
14351
14578
|
onChange: (c, all) => {
|
|
14352
14579
|
setCounts(c);
|
|
@@ -14384,7 +14611,7 @@ function CaptureRun({ sheetId, face: given, className }) {
|
|
|
14384
14611
|
void q2.sync().then(() => void q2.lastSyncedAt().then(setLastSynced));
|
|
14385
14612
|
return () => q2.dispose();
|
|
14386
14613
|
}, [client, host]);
|
|
14387
|
-
|
|
14614
|
+
useEffect38(() => {
|
|
14388
14615
|
if (given !== void 0) return;
|
|
14389
14616
|
let cancelled = false;
|
|
14390
14617
|
void client.captureOpen({ sheet_id: sheetId }).then((res) => {
|
|
@@ -14694,19 +14921,19 @@ function AdHocCaptureSheet({
|
|
|
14694
14921
|
attachmentField,
|
|
14695
14922
|
className
|
|
14696
14923
|
}) {
|
|
14697
|
-
const client =
|
|
14924
|
+
const client = useRecordsClient38();
|
|
14698
14925
|
const host = useRecordsUi();
|
|
14699
14926
|
const table = useTable21(tableId);
|
|
14700
14927
|
const fields = useFields23(tableId);
|
|
14701
|
-
const [mode, setMode] =
|
|
14702
|
-
const [reading, setReading] =
|
|
14703
|
-
const [note, setNote] =
|
|
14704
|
-
const [fileId, setFileId] =
|
|
14705
|
-
const [pending, setPending] =
|
|
14706
|
-
const [saved, setSaved] =
|
|
14707
|
-
const [error, setError] =
|
|
14708
|
-
const [uploadError, setUploadError] =
|
|
14709
|
-
const [flushing, setFlushing] =
|
|
14928
|
+
const [mode, setMode] = useState52("reading");
|
|
14929
|
+
const [reading, setReading] = useState52("");
|
|
14930
|
+
const [note, setNote] = useState52("");
|
|
14931
|
+
const [fileId, setFileId] = useState52(null);
|
|
14932
|
+
const [pending, setPending] = useState52(null);
|
|
14933
|
+
const [saved, setSaved] = useState52([]);
|
|
14934
|
+
const [error, setError] = useState52(null);
|
|
14935
|
+
const [uploadError, setUploadError] = useState52(null);
|
|
14936
|
+
const [flushing, setFlushing] = useState52(false);
|
|
14710
14937
|
const queue = useRef15([]);
|
|
14711
14938
|
const keep = useCallback35(
|
|
14712
14939
|
async (next) => {
|
|
@@ -14716,7 +14943,7 @@ function AdHocCaptureSheet({
|
|
|
14716
14943
|
},
|
|
14717
14944
|
[host]
|
|
14718
14945
|
);
|
|
14719
|
-
|
|
14946
|
+
useEffect39(() => {
|
|
14720
14947
|
let cancelled = false;
|
|
14721
14948
|
void (async () => {
|
|
14722
14949
|
const held = host.captureQueue ? await host.captureQueue.load() : [];
|
|
@@ -14895,17 +15122,17 @@ function AdHocCaptureSheet({
|
|
|
14895
15122
|
}
|
|
14896
15123
|
|
|
14897
15124
|
// src/PortalShell.tsx
|
|
14898
|
-
import { useCallback as useCallback36, useEffect as
|
|
14899
|
-
import { useRecordsClient as
|
|
15125
|
+
import { useCallback as useCallback36, useEffect as useEffect40, useState as useState53 } from "react";
|
|
15126
|
+
import { useRecordsClient as useRecordsClient39 } from "@ai-matrx/records/react";
|
|
14900
15127
|
import { Button as Button48, Skeleton as Skeleton32, cn as cn50 } from "@ai-matrx/design-system";
|
|
14901
15128
|
import { jsx as jsx56, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
14902
15129
|
function PortalShell({ tableId, form, resourceType = "record", className }) {
|
|
14903
|
-
const client =
|
|
14904
|
-
const [card, setCard] =
|
|
14905
|
-
const [reach, setReach] =
|
|
14906
|
-
const [error, setError] =
|
|
14907
|
-
const [open, setOpen] =
|
|
14908
|
-
const [sending, setSending] =
|
|
15130
|
+
const client = useRecordsClient39();
|
|
15131
|
+
const [card, setCard] = useState53(null);
|
|
15132
|
+
const [reach, setReach] = useState53(null);
|
|
15133
|
+
const [error, setError] = useState53(null);
|
|
15134
|
+
const [open, setOpen] = useState53(null);
|
|
15135
|
+
const [sending, setSending] = useState53(false);
|
|
14909
15136
|
const load = useCallback36(async () => {
|
|
14910
15137
|
const who = await client.externalPrincipalCard();
|
|
14911
15138
|
if (!who.ok) {
|
|
@@ -14921,7 +15148,7 @@ function PortalShell({ tableId, form, resourceType = "record", className }) {
|
|
|
14921
15148
|
}
|
|
14922
15149
|
setReach(reached.data.map((row) => row.resource_id));
|
|
14923
15150
|
}, [client, resourceType]);
|
|
14924
|
-
|
|
15151
|
+
useEffect40(() => {
|
|
14925
15152
|
void load();
|
|
14926
15153
|
}, [load]);
|
|
14927
15154
|
if (error) {
|
|
@@ -14979,9 +15206,9 @@ function PortalShell({ tableId, form, resourceType = "record", className }) {
|
|
|
14979
15206
|
] });
|
|
14980
15207
|
}
|
|
14981
15208
|
function PortalRow({ tableId, recordId }) {
|
|
14982
|
-
const client =
|
|
14983
|
-
const [title, setTitle] =
|
|
14984
|
-
|
|
15209
|
+
const client = useRecordsClient39();
|
|
15210
|
+
const [title, setTitle] = useState53(null);
|
|
15211
|
+
useEffect40(() => {
|
|
14985
15212
|
let cancelled = false;
|
|
14986
15213
|
void client.recordRead({ record_id: recordId }).then((answered) => {
|
|
14987
15214
|
if (cancelled) return;
|
|
@@ -15001,17 +15228,17 @@ function PortalRow({ tableId, recordId }) {
|
|
|
15001
15228
|
}
|
|
15002
15229
|
|
|
15003
15230
|
// src/PublicViewPage.tsx
|
|
15004
|
-
import { useCallback as useCallback37, useEffect as
|
|
15005
|
-
import { useRecordsClient as
|
|
15231
|
+
import { useCallback as useCallback37, useEffect as useEffect41, useState as useState54 } from "react";
|
|
15232
|
+
import { useRecordsClient as useRecordsClient40 } from "@ai-matrx/records/react";
|
|
15006
15233
|
import { Skeleton as Skeleton33, cn as cn51 } from "@ai-matrx/design-system";
|
|
15007
15234
|
import { jsx as jsx57, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
15008
15235
|
function PublicViewPage({ slug, className }) {
|
|
15009
|
-
const client =
|
|
15010
|
-
const [binding, setBinding] =
|
|
15011
|
-
const [rows, setRows] =
|
|
15012
|
-
const [fields, setFields] =
|
|
15013
|
-
const [error, setError] =
|
|
15014
|
-
const [gap, setGap] =
|
|
15236
|
+
const client = useRecordsClient40();
|
|
15237
|
+
const [binding, setBinding] = useState54(null);
|
|
15238
|
+
const [rows, setRows] = useState54(null);
|
|
15239
|
+
const [fields, setFields] = useState54(null);
|
|
15240
|
+
const [error, setError] = useState54(null);
|
|
15241
|
+
const [gap, setGap] = useState54(null);
|
|
15015
15242
|
const load = useCallback37(async () => {
|
|
15016
15243
|
const notice = await client.worldPublishGapNotice();
|
|
15017
15244
|
if (notice.ok) setGap(notice.data);
|
|
@@ -15045,7 +15272,7 @@ function PublicViewPage({ slug, className }) {
|
|
|
15045
15272
|
}
|
|
15046
15273
|
setRows([{ id: found.resource_id, document: read.data.document, level: "viewer", hidden: read.data.hidden }]);
|
|
15047
15274
|
}, [client, slug]);
|
|
15048
|
-
|
|
15275
|
+
useEffect41(() => {
|
|
15049
15276
|
void load();
|
|
15050
15277
|
}, [load]);
|
|
15051
15278
|
if (error) return /* @__PURE__ */ jsx57(RefusalNotice, { error, className });
|
|
@@ -15082,8 +15309,8 @@ function PublicRow({ row, fields }) {
|
|
|
15082
15309
|
}
|
|
15083
15310
|
|
|
15084
15311
|
// src/EmbedFrame.tsx
|
|
15085
|
-
import { useCallback as useCallback38, useEffect as
|
|
15086
|
-
import { useRecordsClient as
|
|
15312
|
+
import { useCallback as useCallback38, useEffect as useEffect42, useState as useState55 } from "react";
|
|
15313
|
+
import { useRecordsClient as useRecordsClient41 } from "@ai-matrx/records/react";
|
|
15087
15314
|
import { Button as Button49, Input as Input5, Skeleton as Skeleton34, Textarea as Textarea4, cn as cn52 } from "@ai-matrx/design-system";
|
|
15088
15315
|
import { useTable as useTable22 } from "@ai-matrx/records/react";
|
|
15089
15316
|
import { Fragment as Fragment26, jsx as jsx58, jsxs as jsxs54 } from "react/jsx-runtime";
|
|
@@ -15095,15 +15322,15 @@ function EmbedFrame({
|
|
|
15095
15322
|
embedUrl,
|
|
15096
15323
|
className
|
|
15097
15324
|
}) {
|
|
15098
|
-
const client =
|
|
15325
|
+
const client = useRecordsClient41();
|
|
15099
15326
|
const host = useRecordsUi();
|
|
15100
15327
|
const table = useTable22(tableId);
|
|
15101
15328
|
const rights = useTableRights(table.data);
|
|
15102
|
-
const [origins, setOrigins] =
|
|
15103
|
-
const [secret, setSecret] =
|
|
15104
|
-
const [tokenId, setTokenId] =
|
|
15105
|
-
const [error, setError] =
|
|
15106
|
-
const [busy, setBusy] =
|
|
15329
|
+
const [origins, setOrigins] = useState55("");
|
|
15330
|
+
const [secret, setSecret] = useState55(null);
|
|
15331
|
+
const [tokenId, setTokenId] = useState55(null);
|
|
15332
|
+
const [error, setError] = useState55(null);
|
|
15333
|
+
const [busy, setBusy] = useState55(false);
|
|
15107
15334
|
const mode = formId ? "write" : "read";
|
|
15108
15335
|
const parsed = origins.split(/[\s,]+/).map((o) => o.trim()).filter((o) => o.length > 0);
|
|
15109
15336
|
const issue = useCallback38(async () => {
|
|
@@ -15189,13 +15416,13 @@ function EmbedFrame({
|
|
|
15189
15416
|
] });
|
|
15190
15417
|
}
|
|
15191
15418
|
function useEmbedHandshake(args) {
|
|
15192
|
-
const client =
|
|
15193
|
-
const [binding, setBinding] =
|
|
15194
|
-
const [error, setError] =
|
|
15195
|
-
const [loading, setLoading] =
|
|
15419
|
+
const client = useRecordsClient41();
|
|
15420
|
+
const [binding, setBinding] = useState55(null);
|
|
15421
|
+
const [error, setError] = useState55(null);
|
|
15422
|
+
const [loading, setLoading] = useState55(true);
|
|
15196
15423
|
const origin = args.origin ?? (typeof location === "undefined" ? "" : location.origin);
|
|
15197
15424
|
const { secret, requiredMode } = args;
|
|
15198
|
-
|
|
15425
|
+
useEffect42(() => {
|
|
15199
15426
|
let cancelled = false;
|
|
15200
15427
|
setLoading(true);
|
|
15201
15428
|
setError(null);
|
|
@@ -15250,8 +15477,8 @@ function recordsDataSource(client, fallbackSchema = "custom") {
|
|
|
15250
15477
|
}
|
|
15251
15478
|
|
|
15252
15479
|
// src/TablesHome.tsx
|
|
15253
|
-
import { useCallback as useCallback39, useEffect as
|
|
15254
|
-
import { useRecordsClient as
|
|
15480
|
+
import { useCallback as useCallback39, useEffect as useEffect43, useState as useState56 } from "react";
|
|
15481
|
+
import { useRecordsClient as useRecordsClient42, useTables as useTables4 } from "@ai-matrx/records/react";
|
|
15255
15482
|
import { BasicInput as BasicInput18, Button as Button50, Skeleton as Skeleton35, cn as cn53 } from "@ai-matrx/design-system";
|
|
15256
15483
|
|
|
15257
15484
|
// src/createTable.ts
|
|
@@ -15387,15 +15614,15 @@ function laneFor(table) {
|
|
|
15387
15614
|
return "organization";
|
|
15388
15615
|
}
|
|
15389
15616
|
function TablesHome({ onOpenTable, className }) {
|
|
15390
|
-
const client =
|
|
15617
|
+
const client = useRecordsClient42();
|
|
15391
15618
|
const tables = useTables4();
|
|
15392
|
-
const [creating, setCreating] =
|
|
15393
|
-
const [name, setName] =
|
|
15394
|
-
const [busy, setBusy] =
|
|
15395
|
-
const [error, setError] =
|
|
15396
|
-
const [importInto, setImportInto] =
|
|
15397
|
-
const [boards, setBoards] =
|
|
15398
|
-
|
|
15619
|
+
const [creating, setCreating] = useState56(false);
|
|
15620
|
+
const [name, setName] = useState56("");
|
|
15621
|
+
const [busy, setBusy] = useState56(false);
|
|
15622
|
+
const [error, setError] = useState56(null);
|
|
15623
|
+
const [importInto, setImportInto] = useState56(null);
|
|
15624
|
+
const [boards, setBoards] = useState56(null);
|
|
15625
|
+
useEffect43(() => {
|
|
15399
15626
|
let cancelled = false;
|
|
15400
15627
|
void client.dashboards({}).then((result) => {
|
|
15401
15628
|
if (cancelled) return;
|
|
@@ -15529,8 +15756,8 @@ function TablesHome({ onOpenTable, className }) {
|
|
|
15529
15756
|
}
|
|
15530
15757
|
|
|
15531
15758
|
// src/TablePage.tsx
|
|
15532
|
-
import { useCallback as useCallback40, useEffect as
|
|
15533
|
-
import { useFields as useFields24, useRecordsClient as
|
|
15759
|
+
import { useCallback as useCallback40, useEffect as useEffect44, useState as useState57 } from "react";
|
|
15760
|
+
import { useFields as useFields24, useRecordsClient as useRecordsClient43, useTable as useTable23 } from "@ai-matrx/records/react";
|
|
15534
15761
|
import { Button as Button51, Separator as Separator12, Skeleton as Skeleton36, cn as cn54 } from "@ai-matrx/design-system";
|
|
15535
15762
|
import { Fragment as Fragment28, jsx as jsx61, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
15536
15763
|
function filterInWords(filter, fields) {
|
|
@@ -15612,24 +15839,24 @@ function TablePage({
|
|
|
15612
15839
|
filter,
|
|
15613
15840
|
className
|
|
15614
15841
|
}) {
|
|
15615
|
-
const client =
|
|
15842
|
+
const client = useRecordsClient43();
|
|
15616
15843
|
const table = useTable23(tableId);
|
|
15617
15844
|
const rights = useTableRights(table.data);
|
|
15618
15845
|
const pageFields = useFields24(filter ? tableId : null);
|
|
15619
15846
|
const askedInWords = filter ? filterInWords(filter, pageFields.data ?? []) : null;
|
|
15620
|
-
const organizationId =
|
|
15621
|
-
const [view, setView] =
|
|
15847
|
+
const organizationId = useRecordsClient43().config.organizationId;
|
|
15848
|
+
const [view, setView] = useState57(null);
|
|
15622
15849
|
const opening = openingRail(activeRecordId);
|
|
15623
15850
|
const opened = openingView(activeView, activeDashboardId);
|
|
15624
|
-
const [asking, setAsking] =
|
|
15625
|
-
const [layoutFromLink, setLayoutFromLink] =
|
|
15626
|
-
const [surface, setSurface] =
|
|
15851
|
+
const [asking, setAsking] = useState57(null);
|
|
15852
|
+
const [layoutFromLink, setLayoutFromLink] = useState57(opened.layout);
|
|
15853
|
+
const [surface, setSurface] = useState57({
|
|
15627
15854
|
main: opened.main,
|
|
15628
15855
|
rail: opening.rail
|
|
15629
15856
|
});
|
|
15630
15857
|
const { main, rail } = surface;
|
|
15631
15858
|
const setRail = (next) => setSurface((now) => ({ ...now, rail: next }));
|
|
15632
|
-
const [openRecord, setOpenRecord] =
|
|
15859
|
+
const [openRecord, setOpenRecord] = useState57(opening.record);
|
|
15633
15860
|
const viewVersion = useRecordVersion(view?.id ?? null);
|
|
15634
15861
|
const shownLayout = layoutFromLink ?? view?.layout ?? "grid";
|
|
15635
15862
|
const press = (pressed) => {
|
|
@@ -15640,12 +15867,12 @@ function TablePage({
|
|
|
15640
15867
|
}
|
|
15641
15868
|
};
|
|
15642
15869
|
const show = (next) => press({ rail: next });
|
|
15643
|
-
|
|
15870
|
+
useEffect44(() => {
|
|
15644
15871
|
if (!activeRecordId) return;
|
|
15645
15872
|
setOpenRecord(activeRecordId);
|
|
15646
15873
|
setSurface((now) => ({ ...now, rail: "record" }));
|
|
15647
15874
|
}, [activeRecordId]);
|
|
15648
|
-
|
|
15875
|
+
useEffect44(() => {
|
|
15649
15876
|
const named = pageViewFromParam(activeView);
|
|
15650
15877
|
if (named === null) return;
|
|
15651
15878
|
const isLayout = named !== "dashboards" && named !== "archived";
|