@ai-matrx/records-ui 0.85.6 → 0.85.7
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 +32 -3
- package/dist/index.cjs +370 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -3
- package/dist/index.d.ts +38 -3
- package/dist/index.js +324 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -105,6 +105,7 @@ __export(src_exports, {
|
|
|
105
105
|
GridCell: () => GridCell,
|
|
106
106
|
HistoryPanel: () => HistoryPanel,
|
|
107
107
|
INBOX_GROUPINGS: () => INBOX_GROUPINGS,
|
|
108
|
+
INBOX_VIEWS: () => INBOX_VIEWS,
|
|
108
109
|
IN_MEMORY_QUEUE_REASON: () => IN_MEMORY_QUEUE_REASON,
|
|
109
110
|
ImportWizard: () => ImportWizard,
|
|
110
111
|
KERNEL_REASON: () => KERNEL_REASON,
|
|
@@ -315,6 +316,7 @@ __export(src_exports, {
|
|
|
315
316
|
scalarText: () => scalarText,
|
|
316
317
|
seedIsSatisfied: () => seedIsSatisfied,
|
|
317
318
|
shareUnavailableReason: () => shareUnavailableReason,
|
|
319
|
+
snoozeChoices: () => snoozeChoices,
|
|
318
320
|
specFromBlock: () => specFromBlock,
|
|
319
321
|
storeDecidesRights: () => storeDecidesRights,
|
|
320
322
|
styleFromDecorations: () => styleFromDecorations,
|
|
@@ -3418,6 +3420,7 @@ function OpenCell({
|
|
|
3418
3420
|
// src/Grid.tsx
|
|
3419
3421
|
var import_react30 = require("react");
|
|
3420
3422
|
var import_react31 = require("@ai-matrx/records/react");
|
|
3423
|
+
var import_records9 = require("@ai-matrx/records");
|
|
3421
3424
|
var import_data_table3 = require("@ai-matrx/design-system/data-table");
|
|
3422
3425
|
|
|
3423
3426
|
// src/presentation.ts
|
|
@@ -5778,7 +5781,12 @@ function Grid({
|
|
|
5778
5781
|
recordId: row.id,
|
|
5779
5782
|
title: recordNameIn(table.data, row.document ?? {}),
|
|
5780
5783
|
action: action.name,
|
|
5781
|
-
prompt: action.prompt ?? action.name
|
|
5784
|
+
prompt: action.prompt ?? action.name,
|
|
5785
|
+
// No second read: what the grid holds travels with the press.
|
|
5786
|
+
tableName: table.data ? tableName(table.data) : "",
|
|
5787
|
+
fields: fields.data ?? [],
|
|
5788
|
+
document: row.document ?? {},
|
|
5789
|
+
level: (0, import_records9.asPermissionLevel)(row.level)
|
|
5782
5790
|
})
|
|
5783
5791
|
},
|
|
5784
5792
|
action.id
|
|
@@ -7161,10 +7169,10 @@ var import_design_system22 = require("@ai-matrx/design-system");
|
|
|
7161
7169
|
// src/FormulaTextEditor.tsx
|
|
7162
7170
|
var import_react40 = require("react");
|
|
7163
7171
|
var import_react41 = require("@ai-matrx/records/react");
|
|
7164
|
-
var
|
|
7172
|
+
var import_records10 = require("@ai-matrx/records");
|
|
7165
7173
|
var import_design_system20 = require("@ai-matrx/design-system");
|
|
7166
7174
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
7167
|
-
var FORMULA_FUNCTIONS =
|
|
7175
|
+
var FORMULA_FUNCTIONS = import_records10.RULE_NODE_KINDS.map((row) => row.node).filter((node) => node.startsWith("fx.")).map((node) => node.slice(3).toUpperCase()).filter((name) => !["ADD", "SUB", "MUL", "DIV", "EQ", "NEQ", "GT", "GTE", "LT", "LTE", "NEG", "FIELD", "CONST"].includes(name)).sort();
|
|
7168
7176
|
var RESULT_WORD = {
|
|
7169
7177
|
number: "a number",
|
|
7170
7178
|
text: "text",
|
|
@@ -7385,11 +7393,11 @@ function EntityReferenceKindPicker({ value, onChange, locked = false, className
|
|
|
7385
7393
|
}
|
|
7386
7394
|
|
|
7387
7395
|
// src/FieldEditor.tsx
|
|
7388
|
-
var
|
|
7396
|
+
var import_records11 = require("@ai-matrx/records");
|
|
7389
7397
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
7390
7398
|
var RULE_KINDS = FIELD_RULE_KIND_VALUES.map((kind) => ({ kind, label: FIELD_RULE_KIND_LABEL[kind] }));
|
|
7391
|
-
var SENSITIVITIES =
|
|
7392
|
-
var AGENT_VISIBILITY =
|
|
7399
|
+
var SENSITIVITIES = import_records11.FIELD_SENSITIVITIES.map((value) => ({ value, label: FIELD_SENSITIVITY_LABEL[value] }));
|
|
7400
|
+
var AGENT_VISIBILITY = import_records11.CONTEXT_POLICIES.map((value) => ({ value, label: CONTEXT_POLICY_LABEL[value] }));
|
|
7393
7401
|
var ROLLUP_OPERATIONS = ROLLUP_AGG_VALUES.map((value) => ({
|
|
7394
7402
|
value,
|
|
7395
7403
|
label: ROLLUP_AGG_LABEL[value]
|
|
@@ -10499,14 +10507,14 @@ function viewPatchDocument(patch) {
|
|
|
10499
10507
|
// src/ViewSwitcher.tsx
|
|
10500
10508
|
var import_react65 = require("react");
|
|
10501
10509
|
var import_react66 = require("@ai-matrx/records/react");
|
|
10502
|
-
var
|
|
10510
|
+
var import_records13 = require("@ai-matrx/records");
|
|
10503
10511
|
var import_design_system32 = require("@ai-matrx/design-system");
|
|
10504
10512
|
var import_data_table5 = require("@ai-matrx/design-system/data-table");
|
|
10505
10513
|
|
|
10506
10514
|
// src/Pipeline.tsx
|
|
10507
10515
|
var import_react63 = require("react");
|
|
10508
10516
|
var import_react64 = require("@ai-matrx/records/react");
|
|
10509
|
-
var
|
|
10517
|
+
var import_records12 = require("@ai-matrx/records");
|
|
10510
10518
|
var import_design_system31 = require("@ai-matrx/design-system");
|
|
10511
10519
|
var import_data_table4 = require("@ai-matrx/design-system/data-table");
|
|
10512
10520
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
@@ -10572,7 +10580,7 @@ function PipelineBoard({
|
|
|
10572
10580
|
alive.current = false;
|
|
10573
10581
|
};
|
|
10574
10582
|
}, []);
|
|
10575
|
-
const filterKey = (0,
|
|
10583
|
+
const filterKey = (0, import_records12.stableFilterKey)(filter);
|
|
10576
10584
|
const reload = (0, import_react63.useCallback)(async () => {
|
|
10577
10585
|
setLoading(true);
|
|
10578
10586
|
const [read, board, held] = await Promise.all([
|
|
@@ -11216,8 +11224,8 @@ function useViewRecords(view, pageSize = 200, filter) {
|
|
|
11216
11224
|
cancelled = true;
|
|
11217
11225
|
};
|
|
11218
11226
|
}, [client, ruleId, pageSize]);
|
|
11219
|
-
const asked = (0,
|
|
11220
|
-
const fromView = asked !== "{}" && (asked === (0,
|
|
11227
|
+
const asked = (0, import_records13.stableFilterKey)(filter ?? null);
|
|
11228
|
+
const fromView = asked !== "{}" && (asked === (0, import_records13.stableFilterKey)(view.where ?? null) || asked === (0, import_records13.stableFilterKey)(view.filters ?? null));
|
|
11221
11229
|
const rows = ruleId ? ruled.rows : table.data?.rows ?? [];
|
|
11222
11230
|
return {
|
|
11223
11231
|
rows: sortRows(rows, view.sorts ?? []),
|
|
@@ -11747,7 +11755,7 @@ function Card2({
|
|
|
11747
11755
|
|
|
11748
11756
|
// src/ArchivedView.tsx
|
|
11749
11757
|
var import_react67 = require("react");
|
|
11750
|
-
var
|
|
11758
|
+
var import_records14 = require("@ai-matrx/records");
|
|
11751
11759
|
var import_react68 = require("@ai-matrx/records/react");
|
|
11752
11760
|
var import_design_system33 = require("@ai-matrx/design-system");
|
|
11753
11761
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
@@ -11757,7 +11765,7 @@ function mayNotRestoreLine(why) {
|
|
|
11757
11765
|
return said === "" ? "Bringing a record back needs permission to edit this table. Ask somebody who has it." : said;
|
|
11758
11766
|
}
|
|
11759
11767
|
function archivedRowLine(row, titleKey) {
|
|
11760
|
-
return `${recordName(row.document, titleKey)} \u2014 ${(0,
|
|
11768
|
+
return `${recordName(row.document, titleKey)} \u2014 ${(0, import_records14.archivedByLine)(row)}`;
|
|
11761
11769
|
}
|
|
11762
11770
|
function ArchivedView({
|
|
11763
11771
|
tableId,
|
|
@@ -11771,7 +11779,7 @@ function ArchivedView({
|
|
|
11771
11779
|
const table = (0, import_react68.useTable)(tableId);
|
|
11772
11780
|
const rights = useTableRights(table.data);
|
|
11773
11781
|
const fields = (0, import_react68.useFields)(tableId);
|
|
11774
|
-
const [lane, setLane] = (0, import_react67.useState)(laneFromHost ??
|
|
11782
|
+
const [lane, setLane] = (0, import_react67.useState)(laneFromHost ?? import_records14.DEFAULT_ARCHIVE_LANE);
|
|
11775
11783
|
const [rows, setRows] = (0, import_react67.useState)([]);
|
|
11776
11784
|
const [loading, setLoading] = (0, import_react67.useState)(true);
|
|
11777
11785
|
const [error, setError] = (0, import_react67.useState)(null);
|
|
@@ -11818,15 +11826,15 @@ function ArchivedView({
|
|
|
11818
11826
|
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: (0, import_design_system33.cn)("flex min-h-0 flex-col gap-2", className), "data-testid": "archived-view", children: [
|
|
11819
11827
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
11820
11828
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-sm font-medium", children: "Archived" }),
|
|
11821
|
-
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "ml-auto flex items-center gap-0.5", role: "group", "aria-label": "Archived by", children:
|
|
11829
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "ml-auto flex items-center gap-0.5", role: "group", "aria-label": "Archived by", children: import_records14.ARCHIVE_LANES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
11822
11830
|
import_design_system33.Button,
|
|
11823
11831
|
{
|
|
11824
11832
|
size: "sm",
|
|
11825
11833
|
variant: option === lane ? "secondary" : "ghost",
|
|
11826
11834
|
"aria-pressed": option === lane,
|
|
11827
|
-
title:
|
|
11835
|
+
title: import_records14.ARCHIVE_LANE_MEANS[option],
|
|
11828
11836
|
onClick: () => pick(option),
|
|
11829
|
-
children:
|
|
11837
|
+
children: import_records14.ARCHIVE_LANE_LABEL[option]
|
|
11830
11838
|
},
|
|
11831
11839
|
option
|
|
11832
11840
|
)) })
|
|
@@ -11842,7 +11850,7 @@ function ArchivedView({
|
|
|
11842
11850
|
),
|
|
11843
11851
|
error ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefusalNotice, { error }) : null,
|
|
11844
11852
|
loading && !error ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system33.Skeleton, { className: "h-24 w-full" }) : null,
|
|
11845
|
-
!loading && !error && rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { "data-testid": "archived-empty", className: "rounded-md border border-dashed px-3 py-6 text-xs text-muted-foreground", children: (0,
|
|
11853
|
+
!loading && !error && rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { "data-testid": "archived-empty", className: "rounded-md border border-dashed px-3 py-6 text-xs text-muted-foreground", children: (0, import_records14.emptyArchiveLine)(lane) }) : null,
|
|
11846
11854
|
!loading && !error && rows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("ul", { className: "flex flex-col gap-1", "data-testid": "archived-rows", children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
11847
11855
|
"li",
|
|
11848
11856
|
{
|
|
@@ -11852,7 +11860,7 @@ function ArchivedView({
|
|
|
11852
11860
|
children: [
|
|
11853
11861
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
11854
11862
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "truncate text-sm", children: recordName(row.document, titleKey) }),
|
|
11855
|
-
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "truncate text-xs text-muted-foreground", "data-testid": "archived-who", children: (0,
|
|
11863
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "truncate text-xs text-muted-foreground", "data-testid": "archived-who", children: (0, import_records14.archivedByLine)(row) }),
|
|
11856
11864
|
refusal2 && refusal2.recordId === row.id ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefusalNotice, { error: refusal2.error, className: "mt-2" }) : null
|
|
11857
11865
|
] }),
|
|
11858
11866
|
mayRestore ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
@@ -11875,7 +11883,7 @@ function ArchivedView({
|
|
|
11875
11883
|
|
|
11876
11884
|
// src/ArchivedDisclosure.tsx
|
|
11877
11885
|
var import_react69 = require("react");
|
|
11878
|
-
var
|
|
11886
|
+
var import_records15 = require("@ai-matrx/records");
|
|
11879
11887
|
var import_react70 = require("@ai-matrx/records/react");
|
|
11880
11888
|
var import_design_system34 = require("@ai-matrx/design-system");
|
|
11881
11889
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
@@ -11975,10 +11983,10 @@ function ArchivedPortals({
|
|
|
11975
11983
|
error ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(RefusalNotice, { error }) : null,
|
|
11976
11984
|
rows === null && !error ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system34.Skeleton, { className: "h-16 w-full" }) : null,
|
|
11977
11985
|
said ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "rounded-md border border-border px-3 py-2 text-xs", "data-testid": "archived-portal-said", children: said }) : null,
|
|
11978
|
-
rows !== null && !error && rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { "data-testid": "archived-portals-empty", className: "text-xs text-muted-foreground", children: (0,
|
|
11986
|
+
rows !== null && !error && rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { "data-testid": "archived-portals-empty", className: "text-xs text-muted-foreground", children: (0, import_records15.emptyPortalArchiveLine)() }) : null,
|
|
11979
11987
|
rows !== null && rows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("ul", { className: "flex flex-col gap-1.5", "data-testid": "archived-portals", children: rows.map((portal) => {
|
|
11980
11988
|
const asking = confirming === portal.portal_id;
|
|
11981
|
-
const matches2 = (0,
|
|
11989
|
+
const matches2 = (0, import_records15.portalTitleTypedBack)(typed, portal.title);
|
|
11982
11990
|
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
11983
11991
|
"li",
|
|
11984
11992
|
{
|
|
@@ -12017,7 +12025,7 @@ function ArchivedPortals({
|
|
|
12017
12025
|
] }),
|
|
12018
12026
|
asking ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
|
|
12019
12027
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
|
|
12020
|
-
(0,
|
|
12028
|
+
(0, import_records15.portalConfirmLine)(portal.title),
|
|
12021
12029
|
" Restoring it puts it back exactly as it was: everyone who was invited can sign in again, and it shows the same Tables."
|
|
12022
12030
|
] }),
|
|
12023
12031
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
@@ -12615,9 +12623,18 @@ function useMyChecklistSteps(limit = 25) {
|
|
|
12615
12623
|
}, [refresh]);
|
|
12616
12624
|
return { steps, loading, error, refresh };
|
|
12617
12625
|
}
|
|
12618
|
-
function MyChecklistSteps({
|
|
12626
|
+
function MyChecklistSteps({
|
|
12627
|
+
className,
|
|
12628
|
+
onlyIds,
|
|
12629
|
+
onSteps,
|
|
12630
|
+
actions
|
|
12631
|
+
}) {
|
|
12619
12632
|
const client = (0, import_react78.useRecordsClient)();
|
|
12620
|
-
const { steps, loading, error, refresh } = useMyChecklistSteps();
|
|
12633
|
+
const { steps: held, loading, error, refresh } = useMyChecklistSteps();
|
|
12634
|
+
(0, import_react77.useEffect)(() => {
|
|
12635
|
+
onSteps?.(held.map((s) => s.step_id));
|
|
12636
|
+
}, [held, onSteps]);
|
|
12637
|
+
const steps = onlyIds ? held.filter((s) => onlyIds.has(s.step_id)) : held;
|
|
12621
12638
|
const [busy, setBusy] = (0, import_react77.useState)(null);
|
|
12622
12639
|
const [refusal2, setRefusal] = (0, import_react77.useState)(null);
|
|
12623
12640
|
const complete = (0, import_react77.useCallback)(
|
|
@@ -12643,15 +12660,20 @@ function MyChecklistSteps({ className }) {
|
|
|
12643
12660
|
] }),
|
|
12644
12661
|
error ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(RefusalNotice, { error }) : null,
|
|
12645
12662
|
refusal2 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(RefusalNotice, { error: refusal2 }) : null,
|
|
12646
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ol", { className: "flex flex-col gap-1.5", children: steps.map(
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12654
|
-
|
|
12663
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ol", { className: "flex flex-col gap-1.5", children: steps.map(
|
|
12664
|
+
(step2) => actions ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col gap-0.5", "data-step-row": step2.step_id, children: [
|
|
12665
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(StepRow, { step: step2, busy: busy === step2.step_id, onComplete: (evidence) => void complete(step2, evidence) }),
|
|
12666
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex items-center justify-end gap-1", children: actions(step2.step_id) })
|
|
12667
|
+
] }, step2.step_id) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
12668
|
+
StepRow,
|
|
12669
|
+
{
|
|
12670
|
+
step: step2,
|
|
12671
|
+
busy: busy === step2.step_id,
|
|
12672
|
+
onComplete: (evidence) => void complete(step2, evidence)
|
|
12673
|
+
},
|
|
12674
|
+
step2.step_id
|
|
12675
|
+
)
|
|
12676
|
+
) })
|
|
12655
12677
|
] });
|
|
12656
12678
|
}
|
|
12657
12679
|
function ChecklistsPanel({ tableId, onOpenRecord, className }) {
|
|
@@ -13031,6 +13053,24 @@ var DUE_WORD2 = DUE_STATE_LABEL;
|
|
|
13031
13053
|
var INBOX_GROUPINGS = ["kind", "table", "none"];
|
|
13032
13054
|
var GROUPING_WORD = { kind: "Kind", table: "Table", none: "None" };
|
|
13033
13055
|
var KIND_ORDER = { approval: 0, proposal: 1, assignment: 2 };
|
|
13056
|
+
var INBOX_VIEWS = ["inbox", "snoozed", "done"];
|
|
13057
|
+
var VIEW_WORD = { inbox: "Inbox", snoozed: "Snoozed", done: "Done" };
|
|
13058
|
+
function snoozeChoices(now = /* @__PURE__ */ new Date()) {
|
|
13059
|
+
const at8 = (d) => {
|
|
13060
|
+
const x = new Date(d);
|
|
13061
|
+
x.setHours(8, 0, 0, 0);
|
|
13062
|
+
return x;
|
|
13063
|
+
};
|
|
13064
|
+
const later = new Date(now.getTime() + 3 * 36e5);
|
|
13065
|
+
const tomorrow = at8(new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1));
|
|
13066
|
+
const daysToMonday = (8 - now.getDay()) % 7 || 7;
|
|
13067
|
+
const monday = at8(new Date(now.getFullYear(), now.getMonth(), now.getDate() + daysToMonday));
|
|
13068
|
+
return [
|
|
13069
|
+
{ key: "1", label: "Later today", until: later },
|
|
13070
|
+
{ key: "2", label: "Tomorrow, 8 AM", until: tomorrow },
|
|
13071
|
+
{ key: "3", label: "Next Monday, 8 AM", until: monday }
|
|
13072
|
+
];
|
|
13073
|
+
}
|
|
13034
13074
|
function groupInbox(items, by) {
|
|
13035
13075
|
if (by === "none") return [{ key: "all", label: null, items: [...items] }];
|
|
13036
13076
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -13072,8 +13112,19 @@ function ActionInbox({
|
|
|
13072
13112
|
const anchor = (0, import_react79.useRef)(null);
|
|
13073
13113
|
const [deciding, setDeciding] = (0, import_react79.useState)(false);
|
|
13074
13114
|
const [batchSaid, setBatchSaid] = (0, import_react79.useState)(null);
|
|
13115
|
+
const [view, setView] = (0, import_react79.useState)("inbox");
|
|
13116
|
+
const [counts, setCounts] = (0, import_react79.useState)(null);
|
|
13117
|
+
const [snoozing, setSnoozing] = (0, import_react79.useState)(null);
|
|
13118
|
+
const [pickAt, setPickAt] = (0, import_react79.useState)("");
|
|
13119
|
+
const [said, setSaid] = (0, import_react79.useState)(null);
|
|
13120
|
+
const [stepIds, setStepIds] = (0, import_react79.useState)(/* @__PURE__ */ new Set());
|
|
13121
|
+
const onSteps = (0, import_react79.useCallback)((ids) => setStepIds(new Set(ids)), []);
|
|
13075
13122
|
const load = (0, import_react79.useCallback)(async () => {
|
|
13076
|
-
const result = await
|
|
13123
|
+
const [result, counted] = await Promise.all([
|
|
13124
|
+
client.workInbox({ limit: 200, includeDecided: view === "inbox" && showDecided, view }),
|
|
13125
|
+
client.inboxCounts()
|
|
13126
|
+
]);
|
|
13127
|
+
setCounts(counted.ok ? counted.data[0] ?? null : null);
|
|
13077
13128
|
if (!result.ok) {
|
|
13078
13129
|
setError(result.error);
|
|
13079
13130
|
setItems([]);
|
|
@@ -13081,15 +13132,19 @@ function ActionInbox({
|
|
|
13081
13132
|
}
|
|
13082
13133
|
setError(null);
|
|
13083
13134
|
setItems(result.data);
|
|
13084
|
-
}, [client, showDecided]);
|
|
13135
|
+
}, [client, showDecided, view]);
|
|
13085
13136
|
(0, import_react79.useEffect)(() => {
|
|
13086
13137
|
void load();
|
|
13087
13138
|
}, [load]);
|
|
13088
13139
|
const narrowed = (0, import_react79.useMemo)(() => {
|
|
13089
|
-
const all = items ?? [];
|
|
13140
|
+
const all = (items ?? []).filter((i) => !(view === "inbox" && i.kind === "assignment" && stepIds.has(i.item_id)));
|
|
13090
13141
|
if (!tableId || everyTable) return all;
|
|
13091
13142
|
return all.filter((i) => i.table_id === tableId);
|
|
13092
|
-
}, [items, tableId, everyTable]);
|
|
13143
|
+
}, [items, tableId, everyTable, view, stepIds]);
|
|
13144
|
+
const waitingIds = (0, import_react79.useMemo)(
|
|
13145
|
+
() => new Set((items ?? []).filter((i) => i.kind === "assignment").map((i) => i.item_id)),
|
|
13146
|
+
[items]
|
|
13147
|
+
);
|
|
13093
13148
|
const groups = (0, import_react79.useMemo)(() => groupInbox(narrowed, groupBy), [narrowed, groupBy]);
|
|
13094
13149
|
const shown3 = (0, import_react79.useMemo)(() => groups.flatMap((g) => g.items), [groups]);
|
|
13095
13150
|
const elsewhere = (items?.length ?? 0) - narrowed.length;
|
|
@@ -13148,9 +13203,9 @@ function ActionInbox({
|
|
|
13148
13203
|
setError(result.error);
|
|
13149
13204
|
return;
|
|
13150
13205
|
}
|
|
13151
|
-
const
|
|
13152
|
-
for (const r of result.data.results)
|
|
13153
|
-
setOutcome((o) => ({ ...o, ...
|
|
13206
|
+
const said2 = {};
|
|
13207
|
+
for (const r of result.data.results) said2[r.item] = r.sentence;
|
|
13208
|
+
setOutcome((o) => ({ ...o, ...said2 }));
|
|
13154
13209
|
const { approved, declined, not_decided } = result.data;
|
|
13155
13210
|
setBatchSaid(
|
|
13156
13211
|
[
|
|
@@ -13164,6 +13219,79 @@ function ActionInbox({
|
|
|
13164
13219
|
},
|
|
13165
13220
|
[client, shown3, selected, decidable, load]
|
|
13166
13221
|
);
|
|
13222
|
+
const snooze = (0, import_react79.useCallback)(
|
|
13223
|
+
async (itemId, title, until) => {
|
|
13224
|
+
setSnoozing(null);
|
|
13225
|
+
const result = await client.inboxSnooze({ item_id: itemId, until: until.toISOString() });
|
|
13226
|
+
if (!result.ok) {
|
|
13227
|
+
setError(result.error);
|
|
13228
|
+
return;
|
|
13229
|
+
}
|
|
13230
|
+
setSaid({
|
|
13231
|
+
text: `Snoozed until ${whenWords2(until.toISOString())}: ${title}`,
|
|
13232
|
+
undo: async () => {
|
|
13233
|
+
const back = await client.inboxUnsnooze({ item_id: itemId });
|
|
13234
|
+
if (!back.ok) setError(back.error);
|
|
13235
|
+
else setSaid({ text: back.data.sentence, undo: null });
|
|
13236
|
+
await load();
|
|
13237
|
+
}
|
|
13238
|
+
});
|
|
13239
|
+
await load();
|
|
13240
|
+
},
|
|
13241
|
+
[client, load]
|
|
13242
|
+
);
|
|
13243
|
+
const unsnooze = (0, import_react79.useCallback)(
|
|
13244
|
+
async (itemId) => {
|
|
13245
|
+
const result = await client.inboxUnsnooze({ item_id: itemId });
|
|
13246
|
+
if (!result.ok) {
|
|
13247
|
+
setError(result.error);
|
|
13248
|
+
return;
|
|
13249
|
+
}
|
|
13250
|
+
setSaid({ text: result.data.sentence, undo: null });
|
|
13251
|
+
await load();
|
|
13252
|
+
},
|
|
13253
|
+
[client, load]
|
|
13254
|
+
);
|
|
13255
|
+
const clearItem = (0, import_react79.useCallback)(
|
|
13256
|
+
async (itemId) => {
|
|
13257
|
+
const result = await client.inboxClear({ item_id: itemId });
|
|
13258
|
+
if (!result.ok) {
|
|
13259
|
+
setError(result.error);
|
|
13260
|
+
return;
|
|
13261
|
+
}
|
|
13262
|
+
setSaid({
|
|
13263
|
+
text: result.data.sentence,
|
|
13264
|
+
undo: async () => {
|
|
13265
|
+
const back = await client.inboxUnclear({ item_id: itemId });
|
|
13266
|
+
if (!back.ok) setError(back.error);
|
|
13267
|
+
else setSaid({ text: back.data.sentence, undo: null });
|
|
13268
|
+
await load();
|
|
13269
|
+
}
|
|
13270
|
+
});
|
|
13271
|
+
await load();
|
|
13272
|
+
},
|
|
13273
|
+
[client, load]
|
|
13274
|
+
);
|
|
13275
|
+
const unclear = (0, import_react79.useCallback)(
|
|
13276
|
+
async (itemId) => {
|
|
13277
|
+
const result = await client.inboxUnclear({ item_id: itemId });
|
|
13278
|
+
if (!result.ok) {
|
|
13279
|
+
setError(result.error);
|
|
13280
|
+
return;
|
|
13281
|
+
}
|
|
13282
|
+
setSaid({ text: result.data.sentence, undo: null });
|
|
13283
|
+
await load();
|
|
13284
|
+
},
|
|
13285
|
+
[client, load]
|
|
13286
|
+
);
|
|
13287
|
+
const clearable = (0, import_react79.useCallback)(
|
|
13288
|
+
(item) => item.kind === "assignment" && view === "inbox",
|
|
13289
|
+
[view]
|
|
13290
|
+
);
|
|
13291
|
+
const snoozable = (0, import_react79.useCallback)(
|
|
13292
|
+
(item) => view === "inbox" && (item.kind === "assignment" || item.state === "pending") && !outcome[item.item_id],
|
|
13293
|
+
[view, outcome]
|
|
13294
|
+
);
|
|
13167
13295
|
const open = (0, import_react79.useCallback)(
|
|
13168
13296
|
(item) => {
|
|
13169
13297
|
if (!onOpenRecord || !item.subject_id) return;
|
|
@@ -13175,6 +13303,47 @@ function ActionInbox({
|
|
|
13175
13303
|
(event) => {
|
|
13176
13304
|
const item = shown3[cursor];
|
|
13177
13305
|
const key = event.key;
|
|
13306
|
+
if (event.target?.tagName === "INPUT") return;
|
|
13307
|
+
if (snoozing) {
|
|
13308
|
+
const choice = snoozeChoices().find((c) => c.key === key);
|
|
13309
|
+
const row = shown3.find((i) => i.item_id === snoozing);
|
|
13310
|
+
if (choice && row) {
|
|
13311
|
+
event.preventDefault();
|
|
13312
|
+
void snooze(row.item_id, row.title, choice.until);
|
|
13313
|
+
return;
|
|
13314
|
+
}
|
|
13315
|
+
if (key === "Escape") {
|
|
13316
|
+
event.preventDefault();
|
|
13317
|
+
setSnoozing(null);
|
|
13318
|
+
return;
|
|
13319
|
+
}
|
|
13320
|
+
}
|
|
13321
|
+
if (key === "s" && item && snoozable(item)) {
|
|
13322
|
+
event.preventDefault();
|
|
13323
|
+
setSnoozing((open2) => open2 === item.item_id ? null : item.item_id);
|
|
13324
|
+
return;
|
|
13325
|
+
}
|
|
13326
|
+
if (key === "e" && item && clearable(item)) {
|
|
13327
|
+
event.preventDefault();
|
|
13328
|
+
void clearItem(item.item_id);
|
|
13329
|
+
return;
|
|
13330
|
+
}
|
|
13331
|
+
if (key === "u" && item && view !== "inbox") {
|
|
13332
|
+
event.preventDefault();
|
|
13333
|
+
void (view === "snoozed" ? unsnooze(item.item_id) : unclear(item.item_id));
|
|
13334
|
+
return;
|
|
13335
|
+
}
|
|
13336
|
+
if (key === "z" && said?.undo) {
|
|
13337
|
+
event.preventDefault();
|
|
13338
|
+
void said.undo();
|
|
13339
|
+
return;
|
|
13340
|
+
}
|
|
13341
|
+
if (key === "v") {
|
|
13342
|
+
event.preventDefault();
|
|
13343
|
+
setView((v) => INBOX_VIEWS[(INBOX_VIEWS.indexOf(v) + 1) % INBOX_VIEWS.length]);
|
|
13344
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
13345
|
+
return;
|
|
13346
|
+
}
|
|
13178
13347
|
if (key === "j" || key === "ArrowDown") {
|
|
13179
13348
|
event.preventDefault();
|
|
13180
13349
|
setCursor((c) => Math.min(shown3.length - 1, c + 1));
|
|
@@ -13208,7 +13377,7 @@ function ActionInbox({
|
|
|
13208
13377
|
void decide(item, key === "a");
|
|
13209
13378
|
}
|
|
13210
13379
|
},
|
|
13211
|
-
[shown3, cursor, decide, open, load, decidable, select, selected, decideSelected]
|
|
13380
|
+
[shown3, cursor, decide, open, load, decidable, select, selected, decideSelected, snoozing, snooze, clearItem, unsnooze, unclear, said, view, snoozable, clearable]
|
|
13212
13381
|
);
|
|
13213
13382
|
const renderRow = (item, index) => {
|
|
13214
13383
|
const settled = outcome[item.item_id];
|
|
@@ -13260,9 +13429,84 @@ function ActionInbox({
|
|
|
13260
13429
|
children: DUE_WORD2[item.due_state] ?? item.due_state
|
|
13261
13430
|
}
|
|
13262
13431
|
) : null,
|
|
13432
|
+
view === "snoozed" && item.snoozed_until ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "shrink-0 text-[11px] text-muted-foreground", "data-testid": "inbox-back-at", children: [
|
|
13433
|
+
"Back ",
|
|
13434
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("time", { dateTime: item.snoozed_until, children: whenWords2(item.snoozed_until) })
|
|
13435
|
+
] }) : null,
|
|
13436
|
+
view === "done" && item.cleared_at ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "shrink-0 text-[11px] text-muted-foreground", children: [
|
|
13437
|
+
"Cleared ",
|
|
13438
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("time", { dateTime: item.cleared_at, children: whenWords2(item.cleared_at) })
|
|
13439
|
+
] }) : null,
|
|
13440
|
+
snoozable(item) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
13441
|
+
import_design_system38.Button,
|
|
13442
|
+
{
|
|
13443
|
+
size: "sm",
|
|
13444
|
+
variant: "ghost",
|
|
13445
|
+
className: "h-5 px-1 text-[11px]",
|
|
13446
|
+
"aria-expanded": snoozing === item.item_id,
|
|
13447
|
+
onClick: () => setSnoozing((o) => o === item.item_id ? null : item.item_id),
|
|
13448
|
+
children: "Snooze"
|
|
13449
|
+
}
|
|
13450
|
+
) : null,
|
|
13451
|
+
clearable(item) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void clearItem(item.item_id), children: "Done" }) : null,
|
|
13452
|
+
view === "snoozed" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void unsnooze(item.item_id), children: "Unsnooze" }) : null,
|
|
13453
|
+
view === "done" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void unclear(item.item_id), children: "Put back" }) : null,
|
|
13263
13454
|
item.subject_id && onOpenRecord ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => open(item), children: "Open" }) : null
|
|
13264
13455
|
] }),
|
|
13265
13456
|
item.summary ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", children: item.summary }) : null,
|
|
13457
|
+
snoozing === item.item_id ? (
|
|
13458
|
+
// SUPERHUMAN'S CHOICES, then any moment the person names. The picked time's own Snooze is
|
|
13459
|
+
// absent until a time is picked — never a greyed button that does nothing.
|
|
13460
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
13461
|
+
"div",
|
|
13462
|
+
{
|
|
13463
|
+
role: "group",
|
|
13464
|
+
"aria-label": `Snooze ${item.title} until`,
|
|
13465
|
+
"data-testid": "inbox-snooze-choices",
|
|
13466
|
+
className: "flex flex-wrap items-center gap-1 rounded border border-border bg-muted/40 p-1.5",
|
|
13467
|
+
children: [
|
|
13468
|
+
snoozeChoices().map((c) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
13469
|
+
import_design_system38.Button,
|
|
13470
|
+
{
|
|
13471
|
+
size: "sm",
|
|
13472
|
+
variant: "ghost",
|
|
13473
|
+
className: "h-6 px-2 text-[11px]",
|
|
13474
|
+
title: c.until.toLocaleString(),
|
|
13475
|
+
onClick: () => void snooze(item.item_id, item.title, c.until),
|
|
13476
|
+
children: [
|
|
13477
|
+
c.label,
|
|
13478
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "ml-1 text-muted-foreground", children: c.key })
|
|
13479
|
+
]
|
|
13480
|
+
},
|
|
13481
|
+
c.key
|
|
13482
|
+
)),
|
|
13483
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
13484
|
+
"input",
|
|
13485
|
+
{
|
|
13486
|
+
type: "datetime-local",
|
|
13487
|
+
"aria-label": "Pick a time",
|
|
13488
|
+
value: pickAt,
|
|
13489
|
+
onChange: (e) => setPickAt(e.target.value),
|
|
13490
|
+
className: "h-6 rounded border border-border bg-background px-1 text-[11px]"
|
|
13491
|
+
}
|
|
13492
|
+
),
|
|
13493
|
+
pickAt ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
13494
|
+
import_design_system38.Button,
|
|
13495
|
+
{
|
|
13496
|
+
size: "sm",
|
|
13497
|
+
className: "h-6 px-2 text-[11px]",
|
|
13498
|
+
onClick: () => {
|
|
13499
|
+
const until = new Date(pickAt);
|
|
13500
|
+
setPickAt("");
|
|
13501
|
+
void snooze(item.item_id, item.title, until);
|
|
13502
|
+
},
|
|
13503
|
+
children: "Snooze until then"
|
|
13504
|
+
}
|
|
13505
|
+
) : null
|
|
13506
|
+
]
|
|
13507
|
+
}
|
|
13508
|
+
)
|
|
13509
|
+
) : null,
|
|
13266
13510
|
settled ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs", children: settled }) : item.kind === "assignment" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-[11px] text-muted-foreground", children: item.state === "open" ? "Waiting on you." : `${item.state}.` }) : closed ? (
|
|
13267
13511
|
// A CLOSED ITEM SAYS WHO AND WHEN, and then what happened, in the store's own sentence.
|
|
13268
13512
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex flex-col gap-0.5", "data-testid": "inbox-closed", children: [
|
|
@@ -13302,9 +13546,34 @@ function ActionInbox({
|
|
|
13302
13546
|
"aria-label": "Inbox",
|
|
13303
13547
|
children: [
|
|
13304
13548
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
13305
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h3", { className: "
|
|
13306
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("
|
|
13307
|
-
|
|
13549
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h3", { className: "sr-only", children: "Inbox" }),
|
|
13550
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { role: "tablist", "aria-label": "Inbox views", className: "flex items-center gap-0.5", children: INBOX_VIEWS.map((v) => {
|
|
13551
|
+
const n = counts === null ? v === view ? shown3.length : null : v === "inbox" ? counts.waiting : v === "snoozed" ? counts.snoozed : counts.cleared;
|
|
13552
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
13553
|
+
"button",
|
|
13554
|
+
{
|
|
13555
|
+
type: "button",
|
|
13556
|
+
role: "tab",
|
|
13557
|
+
"aria-selected": view === v,
|
|
13558
|
+
"data-inbox-view": v,
|
|
13559
|
+
onClick: () => {
|
|
13560
|
+
setView(v);
|
|
13561
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
13562
|
+
setSnoozing(null);
|
|
13563
|
+
},
|
|
13564
|
+
className: (0, import_design_system38.cn)(
|
|
13565
|
+
"flex items-baseline gap-1 rounded px-1.5 py-0.5 text-xs",
|
|
13566
|
+
view === v ? "bg-accent font-medium text-foreground" : "text-muted-foreground"
|
|
13567
|
+
),
|
|
13568
|
+
children: [
|
|
13569
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: VIEW_WORD[v] }),
|
|
13570
|
+
n !== null ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "tabular-nums text-[11px] text-muted-foreground", children: n }) : null
|
|
13571
|
+
]
|
|
13572
|
+
},
|
|
13573
|
+
v
|
|
13574
|
+
);
|
|
13575
|
+
}) }),
|
|
13576
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "ml-auto hidden text-[10px] text-muted-foreground lg:inline", children: view === "inbox" ? "j/k move \xB7 x select \xB7 a approve \xB7 d decline \xB7 s snooze \xB7 e done \xB7 z undo \xB7 o open \xB7 v view \xB7 g group \xB7 h decided" : "j/k move \xB7 u put back \xB7 z undo \xB7 o open \xB7 v view \xB7 g group" }),
|
|
13308
13577
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
13309
13578
|
"div",
|
|
13310
13579
|
{
|
|
@@ -13327,7 +13596,7 @@ function ActionInbox({
|
|
|
13327
13596
|
))
|
|
13328
13597
|
}
|
|
13329
13598
|
),
|
|
13330
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-7 px-2 text-xs", onClick: () => setShowDecided((s) => !s), children: showDecided ? "Hide decided" : "Show decided" }),
|
|
13599
|
+
view === "inbox" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-7 px-2 text-xs", onClick: () => setShowDecided((s) => !s), children: showDecided ? "Hide decided" : "Show decided" }) : null,
|
|
13331
13600
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-7 px-2 text-xs", onClick: () => void load(), children: "Refresh" })
|
|
13332
13601
|
] }),
|
|
13333
13602
|
error ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(RefusalNotice, { error }) : null,
|
|
@@ -13372,7 +13641,12 @@ function ActionInbox({
|
|
|
13372
13641
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: batchSaid }),
|
|
13373
13642
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-6 px-2", onClick: () => setBatchSaid(null), children: "Close" })
|
|
13374
13643
|
] }) : null,
|
|
13375
|
-
|
|
13644
|
+
said ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "flex items-center gap-2 text-xs", role: "status", "data-testid": "inbox-said", children: [
|
|
13645
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: said.text }),
|
|
13646
|
+
said.undo ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-6 px-2", onClick: () => void said.undo?.(), children: "Undo" }) : null,
|
|
13647
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-6 px-2", onClick: () => setSaid(null), children: "Close" })
|
|
13648
|
+
] }) : null,
|
|
13649
|
+
shown3.length === 0 && view === "snoozed" && !error ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "inbox-empty", children: "Nothing is snoozed. Press s on a row to put it off until a time; it comes back to the top of your inbox then, and only your inbox changes." }) : shown3.length === 0 && view === "done" && !error ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "inbox-empty", children: "Nothing is cleared. Press e on a piece of work you have seen to take it out of your inbox; it comes back if somebody else changes it." }) : shown3.length === 0 ? (
|
|
13376
13650
|
// AN EMPTY INBOX SAYS WHY — and never under a refusal, where "nothing is waiting" would be
|
|
13377
13651
|
// a guess dressed as an answer.
|
|
13378
13652
|
error ? null : tableId && !everyTable && elsewhere > 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "flex flex-wrap items-center gap-2 text-xs text-muted-foreground", "data-testid": "inbox-empty", children: [
|
|
@@ -13402,7 +13676,31 @@ function ActionInbox({
|
|
|
13402
13676
|
) : null,
|
|
13403
13677
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ol", { className: "flex flex-col gap-1", children: group.items.map((item) => renderRow(item, shown3.indexOf(item))) })
|
|
13404
13678
|
] }, group.key)) }),
|
|
13405
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
13679
|
+
view === "inbox" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
13680
|
+
MyChecklistSteps,
|
|
13681
|
+
{
|
|
13682
|
+
className: "border-t pt-2",
|
|
13683
|
+
onlyIds: waitingIds,
|
|
13684
|
+
onSteps,
|
|
13685
|
+
actions: (stepId) => {
|
|
13686
|
+
const title = items?.find((i) => i.item_id === stepId)?.title ?? "this step";
|
|
13687
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
|
|
13688
|
+
snoozing === stepId ? snoozeChoices().map((c) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
13689
|
+
import_design_system38.Button,
|
|
13690
|
+
{
|
|
13691
|
+
size: "sm",
|
|
13692
|
+
variant: "ghost",
|
|
13693
|
+
className: "h-5 px-1 text-[11px]",
|
|
13694
|
+
onClick: () => void snooze(stepId, title, c.until),
|
|
13695
|
+
children: c.label
|
|
13696
|
+
},
|
|
13697
|
+
c.key
|
|
13698
|
+
)) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => setSnoozing(stepId), children: "Snooze" }),
|
|
13699
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void clearItem(stepId), children: "Done" })
|
|
13700
|
+
] });
|
|
13701
|
+
}
|
|
13702
|
+
}
|
|
13703
|
+
) : null
|
|
13406
13704
|
]
|
|
13407
13705
|
}
|
|
13408
13706
|
);
|
|
@@ -14494,7 +14792,7 @@ function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
|
|
|
14494
14792
|
// src/PortalsPanel.tsx
|
|
14495
14793
|
var import_react91 = require("react");
|
|
14496
14794
|
var import_react92 = require("@ai-matrx/records/react");
|
|
14497
|
-
var
|
|
14795
|
+
var import_records16 = require("@ai-matrx/records");
|
|
14498
14796
|
var import_design_system45 = require("@ai-matrx/design-system");
|
|
14499
14797
|
|
|
14500
14798
|
// src/BuildOrAsk.tsx
|
|
@@ -14943,7 +15241,7 @@ function PortalsPanel({ tableId, activePortalId, className }) {
|
|
|
14943
15241
|
] }) : null,
|
|
14944
15242
|
activePortalId && !shown3.some((p) => p.portal_id === activePortalId) ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "rounded-md border border-amber-600/40 bg-amber-500/5 px-3 py-2 text-xs leading-relaxed text-amber-700 dark:border-amber-400/40 dark:text-amber-300", children: PORTAL_NOT_HERE_LINE }) : null,
|
|
14945
15243
|
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("ul", { className: "flex flex-col gap-2", children: shown3.map((portal) => {
|
|
14946
|
-
const url = `${origin}${(0,
|
|
15244
|
+
const url = `${origin}${(0, import_records16.portalPath)(portal.slug)}`;
|
|
14947
15245
|
const open = openId === portal.portal_id;
|
|
14948
15246
|
const linked = portal.portal_id === activePortalId;
|
|
14949
15247
|
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
@@ -15058,8 +15356,8 @@ function ArchivePortalControl({
|
|
|
15058
15356
|
}
|
|
15059
15357
|
),
|
|
15060
15358
|
asking ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "mt-1.5 flex w-full flex-col gap-1.5 rounded-md border border-dashed border-border p-2.5", children: [
|
|
15061
|
-
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "portal-archive-consequence", children: (0,
|
|
15062
|
-
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-xs text-muted-foreground", children: (0,
|
|
15359
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "portal-archive-consequence", children: (0, import_records16.portalArchiveConsequence)(portal.title, portal.signed_in, portal.invited) }),
|
|
15360
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-xs text-muted-foreground", children: (0, import_records16.portalConfirmLine)(portal.title) }),
|
|
15063
15361
|
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
15064
15362
|
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
15065
15363
|
import_design_system45.BasicInput,
|
|
@@ -15077,7 +15375,7 @@ function ArchivePortalControl({
|
|
|
15077
15375
|
size: "sm",
|
|
15078
15376
|
variant: "destructive",
|
|
15079
15377
|
"data-testid": "portal-archive-do",
|
|
15080
|
-
disabled: busy || !(0,
|
|
15378
|
+
disabled: busy || !(0, import_records16.portalTitleTypedBack)(typed, portal.title),
|
|
15081
15379
|
onClick: () => void go(),
|
|
15082
15380
|
children: busy ? "Archiving\u2026" : "Archive it"
|
|
15083
15381
|
}
|
|
@@ -16236,7 +16534,7 @@ function usePublishGate() {
|
|
|
16236
16534
|
}
|
|
16237
16535
|
|
|
16238
16536
|
// src/FormBuilder.tsx
|
|
16239
|
-
var
|
|
16537
|
+
var import_records17 = require("@ai-matrx/records");
|
|
16240
16538
|
var import_design_system51 = require("@ai-matrx/design-system");
|
|
16241
16539
|
|
|
16242
16540
|
// src/FormRunner.tsx
|
|
@@ -17101,7 +17399,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
|
|
|
17101
17399
|
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
17102
17400
|
PublishRow,
|
|
17103
17401
|
{
|
|
17104
|
-
url: `${publicOrigin}${(0,
|
|
17402
|
+
url: `${publicOrigin}${(0, import_records17.publicFormPath)(draft.id)}`,
|
|
17105
17403
|
state: draft.state,
|
|
17106
17404
|
mayPublish: rights.structure && !publishGate.blocked,
|
|
17107
17405
|
why: publishGate.why ?? rights.why("structure"),
|
|
@@ -18119,7 +18417,7 @@ function SignBlock({ tableId, recordId, render, className }) {
|
|
|
18119
18417
|
// src/ChartBlock.tsx
|
|
18120
18418
|
var import_react115 = require("react");
|
|
18121
18419
|
var import_recharts = require("recharts");
|
|
18122
|
-
var
|
|
18420
|
+
var import_records18 = require("@ai-matrx/records");
|
|
18123
18421
|
var import_core8 = require("@ai-matrx/records/core");
|
|
18124
18422
|
var import_design_system56 = require("@ai-matrx/design-system");
|
|
18125
18423
|
var import_jsx_runtime61 = require("react/jsx-runtime");
|
|
@@ -18190,7 +18488,7 @@ function ChartBlock({ block, subject, className }) {
|
|
|
18190
18488
|
const kind = block.kind;
|
|
18191
18489
|
const tableId = block.table_id ?? subject;
|
|
18192
18490
|
const measures = block.measures && block.measures.length > 0 ? block.measures : [{ op: "count" }];
|
|
18193
|
-
const primary = (0,
|
|
18491
|
+
const primary = (0, import_records18.measureKey)(measures[0]);
|
|
18194
18492
|
const windows = kind === "stuck" ? null : block.compare ?? null;
|
|
18195
18493
|
const compared = !!windows;
|
|
18196
18494
|
const grain = block.bucket?.by ?? null;
|
|
@@ -19110,7 +19408,7 @@ function TargetControl({
|
|
|
19110
19408
|
// src/FormsPanel.tsx
|
|
19111
19409
|
var import_react118 = require("react");
|
|
19112
19410
|
var import_react119 = require("@ai-matrx/records/react");
|
|
19113
|
-
var
|
|
19411
|
+
var import_records19 = require("@ai-matrx/records");
|
|
19114
19412
|
var import_design_system58 = require("@ai-matrx/design-system");
|
|
19115
19413
|
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
19116
19414
|
var FORM_NOT_HERE_LINE = "The link named a form this table does not have \u2014 it may have been removed, or it belongs to another table. The forms this table does have are listed here.";
|
|
@@ -19214,7 +19512,7 @@ function FormsPanel({ tableId, activeFormId, className }) {
|
|
|
19214
19512
|
}
|
|
19215
19513
|
) : null,
|
|
19216
19514
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("ul", { className: "flex flex-col gap-2", children: forms.map((form) => {
|
|
19217
|
-
const url = `${origin}${(0,
|
|
19515
|
+
const url = `${origin}${(0, import_records19.publicFormPath)(form.form_id)}`;
|
|
19218
19516
|
return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
19219
19517
|
"li",
|
|
19220
19518
|
{
|
|
@@ -19279,7 +19577,7 @@ function FormsPanel({ tableId, activeFormId, className }) {
|
|
|
19279
19577
|
// src/BookingBuilder.tsx
|
|
19280
19578
|
var import_react120 = require("react");
|
|
19281
19579
|
var import_react121 = require("@ai-matrx/records/react");
|
|
19282
|
-
var
|
|
19580
|
+
var import_records20 = require("@ai-matrx/records");
|
|
19283
19581
|
var import_design_system59 = require("@ai-matrx/design-system");
|
|
19284
19582
|
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
19285
19583
|
var STORE_ANSWERS_THESE = ["slot", "status", "booked_with"];
|
|
@@ -19423,7 +19721,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
|
|
|
19423
19721
|
if (!rights.structure) {
|
|
19424
19722
|
return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("p", { className: (0, import_design_system59.cn)("text-xs text-muted-foreground", className), children: rights.why("structure") ?? "Making a booking page needs the admin level on this table, because it lets people with no account take time in your calendar." });
|
|
19425
19723
|
}
|
|
19426
|
-
const url = formId ? `${publicOrigin}${(0,
|
|
19724
|
+
const url = formId ? `${publicOrigin}${(0, import_records20.bookingPath)(formId)}` : null;
|
|
19427
19725
|
const shown3 = offer ?? null;
|
|
19428
19726
|
return (
|
|
19429
19727
|
// THE RAIL IS 384px WIDE AND THE VIEWPORT IS NOT (walk 1, 2026-09-21):
|
|
@@ -19625,7 +19923,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
|
|
|
19625
19923
|
// src/BookingSlots.tsx
|
|
19626
19924
|
var import_react122 = require("react");
|
|
19627
19925
|
var import_react123 = require("@ai-matrx/records/react");
|
|
19628
|
-
var
|
|
19926
|
+
var import_records21 = require("@ai-matrx/records");
|
|
19629
19927
|
var import_design_system60 = require("@ai-matrx/design-system");
|
|
19630
19928
|
var import_jsx_runtime65 = require("react/jsx-runtime");
|
|
19631
19929
|
var BOOKING_NOT_HERE_LINE = "The link named a booking page this table does not have \u2014 it may have been closed for good, or it writes into another table. The booking pages this table does have are listed here.";
|
|
@@ -19742,7 +20040,7 @@ function BookingSlots({ tableId, activeBookingId, className }) {
|
|
|
19742
20040
|
" Open the table the appointments should land in to make one."
|
|
19743
20041
|
] }) : null,
|
|
19744
20042
|
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("ul", { className: "flex flex-col gap-2", children: pages.map((page) => {
|
|
19745
|
-
const url = `${origin}${(0,
|
|
20043
|
+
const url = `${origin}${(0, import_records21.bookingPath)(page.form_id)}`;
|
|
19746
20044
|
const mayOpen = levels.data?.[page.table_id] === "admin";
|
|
19747
20045
|
const open = page.published_at !== null && page.closed_at === null;
|
|
19748
20046
|
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
|
|
@@ -19844,7 +20142,7 @@ var import_design_system62 = require("@ai-matrx/design-system");
|
|
|
19844
20142
|
|
|
19845
20143
|
// src/CaptureRun.tsx
|
|
19846
20144
|
var import_react124 = require("react");
|
|
19847
|
-
var
|
|
20145
|
+
var import_records22 = require("@ai-matrx/records");
|
|
19848
20146
|
var import_react125 = require("@ai-matrx/records/react");
|
|
19849
20147
|
var import_design_system61 = require("@ai-matrx/design-system");
|
|
19850
20148
|
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
@@ -19899,7 +20197,7 @@ function CaptureRun({ sheetId, face: given, className }) {
|
|
|
19899
20197
|
const [sending, setSending] = (0, import_react124.useState)(false);
|
|
19900
20198
|
const queueRef = (0, import_react124.useRef)(null);
|
|
19901
20199
|
(0, import_react124.useEffect)(() => {
|
|
19902
|
-
const q2 = (0,
|
|
20200
|
+
const q2 = (0, import_records22.openCaptureQueue)({
|
|
19903
20201
|
onChange: (c, all) => {
|
|
19904
20202
|
setCounts(c);
|
|
19905
20203
|
setItems(all);
|
|
@@ -20166,7 +20464,7 @@ function CaptureRun({ sheetId, face: given, className }) {
|
|
|
20166
20464
|
value: String(answers[q.field] ?? ""),
|
|
20167
20465
|
onChange: (e) => {
|
|
20168
20466
|
const raw = e.target.value;
|
|
20169
|
-
const answered2 = field ? (0,
|
|
20467
|
+
const answered2 = field ? (0, import_records22.coerceTypedAnswer)(field, raw, { label: q.ask ?? (0, import_records22.coercionLabel)(field) }) : { value: raw };
|
|
20170
20468
|
setAnswers((held) => ({
|
|
20171
20469
|
...held,
|
|
20172
20470
|
[q.field]: raw === "" ? "" : "refusal" in answered2 ? raw : answered2.value
|
|
@@ -20823,7 +21121,7 @@ function recordsDataSource(client, fallbackSchema = "custom") {
|
|
|
20823
21121
|
var import_react140 = require("react");
|
|
20824
21122
|
var import_react141 = require("@ai-matrx/records/react");
|
|
20825
21123
|
var import_core10 = require("@ai-matrx/records/core");
|
|
20826
|
-
var
|
|
21124
|
+
var import_records24 = require("@ai-matrx/records");
|
|
20827
21125
|
var import_design_system68 = require("@ai-matrx/design-system");
|
|
20828
21126
|
|
|
20829
21127
|
// src/ExampleTables.tsx
|
|
@@ -20921,7 +21219,7 @@ var import_core9 = require("@ai-matrx/records/core");
|
|
|
20921
21219
|
|
|
20922
21220
|
// src/WhereItLives.tsx
|
|
20923
21221
|
var import_react138 = require("react");
|
|
20924
|
-
var
|
|
21222
|
+
var import_records23 = require("@ai-matrx/records");
|
|
20925
21223
|
var import_react139 = require("@ai-matrx/records/react");
|
|
20926
21224
|
var import_design_system67 = require("@ai-matrx/design-system");
|
|
20927
21225
|
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
@@ -21033,7 +21331,7 @@ function WhereItLives({ tableId, knownOrganizationName, onMoved, variant = "head
|
|
|
21033
21331
|
choosing.name,
|
|
21034
21332
|
"?"
|
|
21035
21333
|
] }),
|
|
21036
|
-
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: (0,
|
|
21334
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: (0, import_records23.moveConsequence)(answer.home, choosing) }),
|
|
21037
21335
|
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "flex gap-2", children: [
|
|
21038
21336
|
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(import_design_system67.Button, { size: "sm", className: "h-7 text-xs", disabled: moving, onClick: () => void move(choosing), children: moving ? `Moving to ${choosing.name}\u2026` : "Move it" }),
|
|
21039
21337
|
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(import_design_system67.Button, { size: "sm", variant: "ghost", className: "h-7 text-xs", disabled: moving, onClick: () => setChoosing(null), children: "Cancel" })
|
|
@@ -21138,7 +21436,7 @@ function TablesHome({ onOpenTable, organizationName, makingOnly = false, classNa
|
|
|
21138
21436
|
alive = false;
|
|
21139
21437
|
};
|
|
21140
21438
|
}, [client]);
|
|
21141
|
-
const listed = facts.phase === "read" ? (0,
|
|
21439
|
+
const listed = facts.phase === "read" ? (0, import_records24.withTablePlacement)(
|
|
21142
21440
|
(0, import_core10.withTableFacts)(tables.data ?? [], facts.rows, me),
|
|
21143
21441
|
facts.rows
|
|
21144
21442
|
) : tables.data ?? [];
|
|
@@ -21343,7 +21641,7 @@ function TablesHome({ onOpenTable, organizationName, makingOnly = false, classNa
|
|
|
21343
21641
|
|
|
21344
21642
|
// src/TablePage.tsx
|
|
21345
21643
|
var import_react144 = require("react");
|
|
21346
|
-
var
|
|
21644
|
+
var import_records25 = require("@ai-matrx/records");
|
|
21347
21645
|
var import_react145 = require("@ai-matrx/records/react");
|
|
21348
21646
|
var import_design_system70 = require("@ai-matrx/design-system");
|
|
21349
21647
|
|
|
@@ -21545,7 +21843,7 @@ function TableNotHere({
|
|
|
21545
21843
|
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: (0, import_design_system70.cn)("flex flex-col items-start gap-2 rounded-md border border-dashed p-6", className), children: [
|
|
21546
21844
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "text-sm font-medium", children: "This table is archived" }),
|
|
21547
21845
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "max-w-prose text-xs text-muted-foreground", children: TABLE_IS_ARCHIVED }),
|
|
21548
|
-
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "text-xs text-muted-foreground", children: (0,
|
|
21846
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "text-xs text-muted-foreground", children: (0, import_records25.archivedByLine)(row) }),
|
|
21549
21847
|
refusal2 ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(RefusalNotice, { error: refusal2 }) : null,
|
|
21550
21848
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "flex gap-2", children: [
|
|
21551
21849
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|