@ai-matrx/records-ui 0.85.6 → 0.85.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -3
- package/dist/index.cjs +456 -130
- 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 +411 -85
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3102,6 +3102,7 @@ import {
|
|
|
3102
3102
|
useRecordsClient as useRecordsClient9,
|
|
3103
3103
|
useTable as useTable2
|
|
3104
3104
|
} from "@ai-matrx/records/react";
|
|
3105
|
+
import { asPermissionLevel } from "@ai-matrx/records";
|
|
3105
3106
|
import { MatrxDataTable, tableStyleIsEmpty as tableStyleIsEmpty2 } from "@ai-matrx/design-system/data-table";
|
|
3106
3107
|
|
|
3107
3108
|
// src/presentation.ts
|
|
@@ -5501,7 +5502,12 @@ function Grid({
|
|
|
5501
5502
|
recordId: row.id,
|
|
5502
5503
|
title: recordNameIn(table.data, row.document ?? {}),
|
|
5503
5504
|
action: action.name,
|
|
5504
|
-
prompt: action.prompt ?? action.name
|
|
5505
|
+
prompt: action.prompt ?? action.name,
|
|
5506
|
+
// No second read: what the grid holds travels with the press.
|
|
5507
|
+
tableName: table.data ? tableName(table.data) : "",
|
|
5508
|
+
fields: fields.data ?? [],
|
|
5509
|
+
document: row.document ?? {},
|
|
5510
|
+
level: asPermissionLevel(row.level)
|
|
5505
5511
|
})
|
|
5506
5512
|
},
|
|
5507
5513
|
action.id
|
|
@@ -12423,9 +12429,18 @@ function useMyChecklistSteps(limit = 25) {
|
|
|
12423
12429
|
}, [refresh]);
|
|
12424
12430
|
return { steps, loading, error, refresh };
|
|
12425
12431
|
}
|
|
12426
|
-
function MyChecklistSteps({
|
|
12432
|
+
function MyChecklistSteps({
|
|
12433
|
+
className,
|
|
12434
|
+
onlyIds,
|
|
12435
|
+
onSteps,
|
|
12436
|
+
actions
|
|
12437
|
+
}) {
|
|
12427
12438
|
const client = useRecordsClient26();
|
|
12428
|
-
const { steps, loading, error, refresh } = useMyChecklistSteps();
|
|
12439
|
+
const { steps: held, loading, error, refresh } = useMyChecklistSteps();
|
|
12440
|
+
useEffect25(() => {
|
|
12441
|
+
onSteps?.(held.map((s) => s.step_id));
|
|
12442
|
+
}, [held, onSteps]);
|
|
12443
|
+
const steps = onlyIds ? held.filter((s) => onlyIds.has(s.step_id)) : held;
|
|
12429
12444
|
const [busy, setBusy] = useState37(null);
|
|
12430
12445
|
const [refusal2, setRefusal] = useState37(null);
|
|
12431
12446
|
const complete = useCallback18(
|
|
@@ -12451,15 +12466,20 @@ function MyChecklistSteps({ className }) {
|
|
|
12451
12466
|
] }),
|
|
12452
12467
|
error ? /* @__PURE__ */ jsx42(RefusalNotice, { error }) : null,
|
|
12453
12468
|
refusal2 ? /* @__PURE__ */ jsx42(RefusalNotice, { error: refusal2 }) : null,
|
|
12454
|
-
/* @__PURE__ */ jsx42("ol", { className: "flex flex-col gap-1.5", children: steps.map(
|
|
12455
|
-
|
|
12456
|
-
|
|
12457
|
-
|
|
12458
|
-
|
|
12459
|
-
|
|
12460
|
-
|
|
12461
|
-
|
|
12462
|
-
|
|
12469
|
+
/* @__PURE__ */ jsx42("ol", { className: "flex flex-col gap-1.5", children: steps.map(
|
|
12470
|
+
(step2) => actions ? /* @__PURE__ */ jsxs37("div", { className: "flex flex-col gap-0.5", "data-step-row": step2.step_id, children: [
|
|
12471
|
+
/* @__PURE__ */ jsx42(StepRow, { step: step2, busy: busy === step2.step_id, onComplete: (evidence) => void complete(step2, evidence) }),
|
|
12472
|
+
/* @__PURE__ */ jsx42("div", { className: "flex items-center justify-end gap-1", children: actions(step2.step_id) })
|
|
12473
|
+
] }, step2.step_id) : /* @__PURE__ */ jsx42(
|
|
12474
|
+
StepRow,
|
|
12475
|
+
{
|
|
12476
|
+
step: step2,
|
|
12477
|
+
busy: busy === step2.step_id,
|
|
12478
|
+
onComplete: (evidence) => void complete(step2, evidence)
|
|
12479
|
+
},
|
|
12480
|
+
step2.step_id
|
|
12481
|
+
)
|
|
12482
|
+
) })
|
|
12463
12483
|
] });
|
|
12464
12484
|
}
|
|
12465
12485
|
function ChecklistsPanel({ tableId, onOpenRecord, className }) {
|
|
@@ -12839,6 +12859,24 @@ var DUE_WORD2 = DUE_STATE_LABEL;
|
|
|
12839
12859
|
var INBOX_GROUPINGS = ["kind", "table", "none"];
|
|
12840
12860
|
var GROUPING_WORD = { kind: "Kind", table: "Table", none: "None" };
|
|
12841
12861
|
var KIND_ORDER = { approval: 0, proposal: 1, assignment: 2 };
|
|
12862
|
+
var INBOX_VIEWS = ["inbox", "snoozed", "done"];
|
|
12863
|
+
var VIEW_WORD = { inbox: "Inbox", snoozed: "Snoozed", done: "Done" };
|
|
12864
|
+
function snoozeChoices(now = /* @__PURE__ */ new Date()) {
|
|
12865
|
+
const at8 = (d) => {
|
|
12866
|
+
const x = new Date(d);
|
|
12867
|
+
x.setHours(8, 0, 0, 0);
|
|
12868
|
+
return x;
|
|
12869
|
+
};
|
|
12870
|
+
const later = new Date(now.getTime() + 3 * 36e5);
|
|
12871
|
+
const tomorrow = at8(new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1));
|
|
12872
|
+
const daysToMonday = (8 - now.getDay()) % 7 || 7;
|
|
12873
|
+
const monday = at8(new Date(now.getFullYear(), now.getMonth(), now.getDate() + daysToMonday));
|
|
12874
|
+
return [
|
|
12875
|
+
{ key: "1", label: "Later today", until: later },
|
|
12876
|
+
{ key: "2", label: "Tomorrow, 8 AM", until: tomorrow },
|
|
12877
|
+
{ key: "3", label: "Next Monday, 8 AM", until: monday }
|
|
12878
|
+
];
|
|
12879
|
+
}
|
|
12842
12880
|
function groupInbox(items, by) {
|
|
12843
12881
|
if (by === "none") return [{ key: "all", label: null, items: [...items] }];
|
|
12844
12882
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -12880,8 +12918,19 @@ function ActionInbox({
|
|
|
12880
12918
|
const anchor = useRef10(null);
|
|
12881
12919
|
const [deciding, setDeciding] = useState38(false);
|
|
12882
12920
|
const [batchSaid, setBatchSaid] = useState38(null);
|
|
12921
|
+
const [view, setView] = useState38("inbox");
|
|
12922
|
+
const [counts, setCounts] = useState38(null);
|
|
12923
|
+
const [snoozing, setSnoozing] = useState38(null);
|
|
12924
|
+
const [pickAt, setPickAt] = useState38("");
|
|
12925
|
+
const [said, setSaid] = useState38(null);
|
|
12926
|
+
const [stepIds, setStepIds] = useState38(/* @__PURE__ */ new Set());
|
|
12927
|
+
const onSteps = useCallback19((ids) => setStepIds(new Set(ids)), []);
|
|
12883
12928
|
const load = useCallback19(async () => {
|
|
12884
|
-
const result = await
|
|
12929
|
+
const [result, counted] = await Promise.all([
|
|
12930
|
+
client.workInbox({ limit: 200, includeDecided: view === "inbox" && showDecided, view }),
|
|
12931
|
+
client.inboxCounts()
|
|
12932
|
+
]);
|
|
12933
|
+
setCounts(counted.ok ? counted.data[0] ?? null : null);
|
|
12885
12934
|
if (!result.ok) {
|
|
12886
12935
|
setError(result.error);
|
|
12887
12936
|
setItems([]);
|
|
@@ -12889,15 +12938,19 @@ function ActionInbox({
|
|
|
12889
12938
|
}
|
|
12890
12939
|
setError(null);
|
|
12891
12940
|
setItems(result.data);
|
|
12892
|
-
}, [client, showDecided]);
|
|
12941
|
+
}, [client, showDecided, view]);
|
|
12893
12942
|
useEffect26(() => {
|
|
12894
12943
|
void load();
|
|
12895
12944
|
}, [load]);
|
|
12896
12945
|
const narrowed = useMemo26(() => {
|
|
12897
|
-
const all = items ?? [];
|
|
12946
|
+
const all = (items ?? []).filter((i) => !(view === "inbox" && i.kind === "assignment" && stepIds.has(i.item_id)));
|
|
12898
12947
|
if (!tableId || everyTable) return all;
|
|
12899
12948
|
return all.filter((i) => i.table_id === tableId);
|
|
12900
|
-
}, [items, tableId, everyTable]);
|
|
12949
|
+
}, [items, tableId, everyTable, view, stepIds]);
|
|
12950
|
+
const waitingIds = useMemo26(
|
|
12951
|
+
() => new Set((items ?? []).filter((i) => i.kind === "assignment").map((i) => i.item_id)),
|
|
12952
|
+
[items]
|
|
12953
|
+
);
|
|
12901
12954
|
const groups = useMemo26(() => groupInbox(narrowed, groupBy), [narrowed, groupBy]);
|
|
12902
12955
|
const shown3 = useMemo26(() => groups.flatMap((g) => g.items), [groups]);
|
|
12903
12956
|
const elsewhere = (items?.length ?? 0) - narrowed.length;
|
|
@@ -12956,9 +13009,9 @@ function ActionInbox({
|
|
|
12956
13009
|
setError(result.error);
|
|
12957
13010
|
return;
|
|
12958
13011
|
}
|
|
12959
|
-
const
|
|
12960
|
-
for (const r of result.data.results)
|
|
12961
|
-
setOutcome((o) => ({ ...o, ...
|
|
13012
|
+
const said2 = {};
|
|
13013
|
+
for (const r of result.data.results) said2[r.item] = r.sentence;
|
|
13014
|
+
setOutcome((o) => ({ ...o, ...said2 }));
|
|
12962
13015
|
const { approved, declined, not_decided } = result.data;
|
|
12963
13016
|
setBatchSaid(
|
|
12964
13017
|
[
|
|
@@ -12972,6 +13025,79 @@ function ActionInbox({
|
|
|
12972
13025
|
},
|
|
12973
13026
|
[client, shown3, selected, decidable, load]
|
|
12974
13027
|
);
|
|
13028
|
+
const snooze = useCallback19(
|
|
13029
|
+
async (itemId, title, until) => {
|
|
13030
|
+
setSnoozing(null);
|
|
13031
|
+
const result = await client.inboxSnooze({ item_id: itemId, until: until.toISOString() });
|
|
13032
|
+
if (!result.ok) {
|
|
13033
|
+
setError(result.error);
|
|
13034
|
+
return;
|
|
13035
|
+
}
|
|
13036
|
+
setSaid({
|
|
13037
|
+
text: `Snoozed until ${whenWords2(until.toISOString())}: ${title}`,
|
|
13038
|
+
undo: async () => {
|
|
13039
|
+
const back = await client.inboxUnsnooze({ item_id: itemId });
|
|
13040
|
+
if (!back.ok) setError(back.error);
|
|
13041
|
+
else setSaid({ text: back.data.sentence, undo: null });
|
|
13042
|
+
await load();
|
|
13043
|
+
}
|
|
13044
|
+
});
|
|
13045
|
+
await load();
|
|
13046
|
+
},
|
|
13047
|
+
[client, load]
|
|
13048
|
+
);
|
|
13049
|
+
const unsnooze = useCallback19(
|
|
13050
|
+
async (itemId) => {
|
|
13051
|
+
const result = await client.inboxUnsnooze({ item_id: itemId });
|
|
13052
|
+
if (!result.ok) {
|
|
13053
|
+
setError(result.error);
|
|
13054
|
+
return;
|
|
13055
|
+
}
|
|
13056
|
+
setSaid({ text: result.data.sentence, undo: null });
|
|
13057
|
+
await load();
|
|
13058
|
+
},
|
|
13059
|
+
[client, load]
|
|
13060
|
+
);
|
|
13061
|
+
const clearItem = useCallback19(
|
|
13062
|
+
async (itemId) => {
|
|
13063
|
+
const result = await client.inboxClear({ item_id: itemId });
|
|
13064
|
+
if (!result.ok) {
|
|
13065
|
+
setError(result.error);
|
|
13066
|
+
return;
|
|
13067
|
+
}
|
|
13068
|
+
setSaid({
|
|
13069
|
+
text: result.data.sentence,
|
|
13070
|
+
undo: async () => {
|
|
13071
|
+
const back = await client.inboxUnclear({ item_id: itemId });
|
|
13072
|
+
if (!back.ok) setError(back.error);
|
|
13073
|
+
else setSaid({ text: back.data.sentence, undo: null });
|
|
13074
|
+
await load();
|
|
13075
|
+
}
|
|
13076
|
+
});
|
|
13077
|
+
await load();
|
|
13078
|
+
},
|
|
13079
|
+
[client, load]
|
|
13080
|
+
);
|
|
13081
|
+
const unclear = useCallback19(
|
|
13082
|
+
async (itemId) => {
|
|
13083
|
+
const result = await client.inboxUnclear({ item_id: itemId });
|
|
13084
|
+
if (!result.ok) {
|
|
13085
|
+
setError(result.error);
|
|
13086
|
+
return;
|
|
13087
|
+
}
|
|
13088
|
+
setSaid({ text: result.data.sentence, undo: null });
|
|
13089
|
+
await load();
|
|
13090
|
+
},
|
|
13091
|
+
[client, load]
|
|
13092
|
+
);
|
|
13093
|
+
const clearable = useCallback19(
|
|
13094
|
+
(item) => item.kind === "assignment" && view === "inbox",
|
|
13095
|
+
[view]
|
|
13096
|
+
);
|
|
13097
|
+
const snoozable = useCallback19(
|
|
13098
|
+
(item) => view === "inbox" && (item.kind === "assignment" || item.state === "pending") && !outcome[item.item_id],
|
|
13099
|
+
[view, outcome]
|
|
13100
|
+
);
|
|
12975
13101
|
const open = useCallback19(
|
|
12976
13102
|
(item) => {
|
|
12977
13103
|
if (!onOpenRecord || !item.subject_id) return;
|
|
@@ -12983,6 +13109,47 @@ function ActionInbox({
|
|
|
12983
13109
|
(event) => {
|
|
12984
13110
|
const item = shown3[cursor];
|
|
12985
13111
|
const key = event.key;
|
|
13112
|
+
if (event.target?.tagName === "INPUT") return;
|
|
13113
|
+
if (snoozing) {
|
|
13114
|
+
const choice = snoozeChoices().find((c) => c.key === key);
|
|
13115
|
+
const row = shown3.find((i) => i.item_id === snoozing);
|
|
13116
|
+
if (choice && row) {
|
|
13117
|
+
event.preventDefault();
|
|
13118
|
+
void snooze(row.item_id, row.title, choice.until);
|
|
13119
|
+
return;
|
|
13120
|
+
}
|
|
13121
|
+
if (key === "Escape") {
|
|
13122
|
+
event.preventDefault();
|
|
13123
|
+
setSnoozing(null);
|
|
13124
|
+
return;
|
|
13125
|
+
}
|
|
13126
|
+
}
|
|
13127
|
+
if (key === "s" && item && snoozable(item)) {
|
|
13128
|
+
event.preventDefault();
|
|
13129
|
+
setSnoozing((open2) => open2 === item.item_id ? null : item.item_id);
|
|
13130
|
+
return;
|
|
13131
|
+
}
|
|
13132
|
+
if (key === "e" && item && clearable(item)) {
|
|
13133
|
+
event.preventDefault();
|
|
13134
|
+
void clearItem(item.item_id);
|
|
13135
|
+
return;
|
|
13136
|
+
}
|
|
13137
|
+
if (key === "u" && item && view !== "inbox") {
|
|
13138
|
+
event.preventDefault();
|
|
13139
|
+
void (view === "snoozed" ? unsnooze(item.item_id) : unclear(item.item_id));
|
|
13140
|
+
return;
|
|
13141
|
+
}
|
|
13142
|
+
if (key === "z" && said?.undo) {
|
|
13143
|
+
event.preventDefault();
|
|
13144
|
+
void said.undo();
|
|
13145
|
+
return;
|
|
13146
|
+
}
|
|
13147
|
+
if (key === "v") {
|
|
13148
|
+
event.preventDefault();
|
|
13149
|
+
setView((v) => INBOX_VIEWS[(INBOX_VIEWS.indexOf(v) + 1) % INBOX_VIEWS.length]);
|
|
13150
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
13151
|
+
return;
|
|
13152
|
+
}
|
|
12986
13153
|
if (key === "j" || key === "ArrowDown") {
|
|
12987
13154
|
event.preventDefault();
|
|
12988
13155
|
setCursor((c) => Math.min(shown3.length - 1, c + 1));
|
|
@@ -13016,7 +13183,7 @@ function ActionInbox({
|
|
|
13016
13183
|
void decide(item, key === "a");
|
|
13017
13184
|
}
|
|
13018
13185
|
},
|
|
13019
|
-
[shown3, cursor, decide, open, load, decidable, select, selected, decideSelected]
|
|
13186
|
+
[shown3, cursor, decide, open, load, decidable, select, selected, decideSelected, snoozing, snooze, clearItem, unsnooze, unclear, said, view, snoozable, clearable]
|
|
13020
13187
|
);
|
|
13021
13188
|
const renderRow = (item, index) => {
|
|
13022
13189
|
const settled = outcome[item.item_id];
|
|
@@ -13068,9 +13235,84 @@ function ActionInbox({
|
|
|
13068
13235
|
children: DUE_WORD2[item.due_state] ?? item.due_state
|
|
13069
13236
|
}
|
|
13070
13237
|
) : null,
|
|
13238
|
+
view === "snoozed" && item.snoozed_until ? /* @__PURE__ */ jsxs38("span", { className: "shrink-0 text-[11px] text-muted-foreground", "data-testid": "inbox-back-at", children: [
|
|
13239
|
+
"Back ",
|
|
13240
|
+
/* @__PURE__ */ jsx43("time", { dateTime: item.snoozed_until, children: whenWords2(item.snoozed_until) })
|
|
13241
|
+
] }) : null,
|
|
13242
|
+
view === "done" && item.cleared_at ? /* @__PURE__ */ jsxs38("span", { className: "shrink-0 text-[11px] text-muted-foreground", children: [
|
|
13243
|
+
"Cleared ",
|
|
13244
|
+
/* @__PURE__ */ jsx43("time", { dateTime: item.cleared_at, children: whenWords2(item.cleared_at) })
|
|
13245
|
+
] }) : null,
|
|
13246
|
+
snoozable(item) ? /* @__PURE__ */ jsx43(
|
|
13247
|
+
Button34,
|
|
13248
|
+
{
|
|
13249
|
+
size: "sm",
|
|
13250
|
+
variant: "ghost",
|
|
13251
|
+
className: "h-5 px-1 text-[11px]",
|
|
13252
|
+
"aria-expanded": snoozing === item.item_id,
|
|
13253
|
+
onClick: () => setSnoozing((o) => o === item.item_id ? null : item.item_id),
|
|
13254
|
+
children: "Snooze"
|
|
13255
|
+
}
|
|
13256
|
+
) : null,
|
|
13257
|
+
clearable(item) ? /* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void clearItem(item.item_id), children: "Done" }) : null,
|
|
13258
|
+
view === "snoozed" ? /* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void unsnooze(item.item_id), children: "Unsnooze" }) : null,
|
|
13259
|
+
view === "done" ? /* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void unclear(item.item_id), children: "Put back" }) : null,
|
|
13071
13260
|
item.subject_id && onOpenRecord ? /* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => open(item), children: "Open" }) : null
|
|
13072
13261
|
] }),
|
|
13073
13262
|
item.summary ? /* @__PURE__ */ jsx43("p", { className: "text-xs text-muted-foreground", children: item.summary }) : null,
|
|
13263
|
+
snoozing === item.item_id ? (
|
|
13264
|
+
// SUPERHUMAN'S CHOICES, then any moment the person names. The picked time's own Snooze is
|
|
13265
|
+
// absent until a time is picked — never a greyed button that does nothing.
|
|
13266
|
+
/* @__PURE__ */ jsxs38(
|
|
13267
|
+
"div",
|
|
13268
|
+
{
|
|
13269
|
+
role: "group",
|
|
13270
|
+
"aria-label": `Snooze ${item.title} until`,
|
|
13271
|
+
"data-testid": "inbox-snooze-choices",
|
|
13272
|
+
className: "flex flex-wrap items-center gap-1 rounded border border-border bg-muted/40 p-1.5",
|
|
13273
|
+
children: [
|
|
13274
|
+
snoozeChoices().map((c) => /* @__PURE__ */ jsxs38(
|
|
13275
|
+
Button34,
|
|
13276
|
+
{
|
|
13277
|
+
size: "sm",
|
|
13278
|
+
variant: "ghost",
|
|
13279
|
+
className: "h-6 px-2 text-[11px]",
|
|
13280
|
+
title: c.until.toLocaleString(),
|
|
13281
|
+
onClick: () => void snooze(item.item_id, item.title, c.until),
|
|
13282
|
+
children: [
|
|
13283
|
+
c.label,
|
|
13284
|
+
/* @__PURE__ */ jsx43("span", { className: "ml-1 text-muted-foreground", children: c.key })
|
|
13285
|
+
]
|
|
13286
|
+
},
|
|
13287
|
+
c.key
|
|
13288
|
+
)),
|
|
13289
|
+
/* @__PURE__ */ jsx43(
|
|
13290
|
+
"input",
|
|
13291
|
+
{
|
|
13292
|
+
type: "datetime-local",
|
|
13293
|
+
"aria-label": "Pick a time",
|
|
13294
|
+
value: pickAt,
|
|
13295
|
+
onChange: (e) => setPickAt(e.target.value),
|
|
13296
|
+
className: "h-6 rounded border border-border bg-background px-1 text-[11px]"
|
|
13297
|
+
}
|
|
13298
|
+
),
|
|
13299
|
+
pickAt ? /* @__PURE__ */ jsx43(
|
|
13300
|
+
Button34,
|
|
13301
|
+
{
|
|
13302
|
+
size: "sm",
|
|
13303
|
+
className: "h-6 px-2 text-[11px]",
|
|
13304
|
+
onClick: () => {
|
|
13305
|
+
const until = new Date(pickAt);
|
|
13306
|
+
setPickAt("");
|
|
13307
|
+
void snooze(item.item_id, item.title, until);
|
|
13308
|
+
},
|
|
13309
|
+
children: "Snooze until then"
|
|
13310
|
+
}
|
|
13311
|
+
) : null
|
|
13312
|
+
]
|
|
13313
|
+
}
|
|
13314
|
+
)
|
|
13315
|
+
) : null,
|
|
13074
13316
|
settled ? /* @__PURE__ */ jsx43("p", { className: "text-xs", children: settled }) : item.kind === "assignment" ? /* @__PURE__ */ jsx43("p", { className: "text-[11px] text-muted-foreground", children: item.state === "open" ? "Waiting on you." : `${item.state}.` }) : closed ? (
|
|
13075
13317
|
// A CLOSED ITEM SAYS WHO AND WHEN, and then what happened, in the store's own sentence.
|
|
13076
13318
|
/* @__PURE__ */ jsxs38("div", { className: "flex flex-col gap-0.5", "data-testid": "inbox-closed", children: [
|
|
@@ -13110,9 +13352,34 @@ function ActionInbox({
|
|
|
13110
13352
|
"aria-label": "Inbox",
|
|
13111
13353
|
children: [
|
|
13112
13354
|
/* @__PURE__ */ jsxs38("div", { className: "flex items-center gap-2", children: [
|
|
13113
|
-
/* @__PURE__ */ jsx43("h3", { className: "
|
|
13114
|
-
/* @__PURE__ */ jsx43("
|
|
13115
|
-
|
|
13355
|
+
/* @__PURE__ */ jsx43("h3", { className: "sr-only", children: "Inbox" }),
|
|
13356
|
+
/* @__PURE__ */ jsx43("div", { role: "tablist", "aria-label": "Inbox views", className: "flex items-center gap-0.5", children: INBOX_VIEWS.map((v) => {
|
|
13357
|
+
const n = counts === null ? v === view ? shown3.length : null : v === "inbox" ? counts.waiting : v === "snoozed" ? counts.snoozed : counts.cleared;
|
|
13358
|
+
return /* @__PURE__ */ jsxs38(
|
|
13359
|
+
"button",
|
|
13360
|
+
{
|
|
13361
|
+
type: "button",
|
|
13362
|
+
role: "tab",
|
|
13363
|
+
"aria-selected": view === v,
|
|
13364
|
+
"data-inbox-view": v,
|
|
13365
|
+
onClick: () => {
|
|
13366
|
+
setView(v);
|
|
13367
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
13368
|
+
setSnoozing(null);
|
|
13369
|
+
},
|
|
13370
|
+
className: cn34(
|
|
13371
|
+
"flex items-baseline gap-1 rounded px-1.5 py-0.5 text-xs",
|
|
13372
|
+
view === v ? "bg-accent font-medium text-foreground" : "text-muted-foreground"
|
|
13373
|
+
),
|
|
13374
|
+
children: [
|
|
13375
|
+
/* @__PURE__ */ jsx43("span", { children: VIEW_WORD[v] }),
|
|
13376
|
+
n !== null ? /* @__PURE__ */ jsx43("span", { className: "tabular-nums text-[11px] text-muted-foreground", children: n }) : null
|
|
13377
|
+
]
|
|
13378
|
+
},
|
|
13379
|
+
v
|
|
13380
|
+
);
|
|
13381
|
+
}) }),
|
|
13382
|
+
/* @__PURE__ */ jsx43("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" }),
|
|
13116
13383
|
/* @__PURE__ */ jsx43(
|
|
13117
13384
|
"div",
|
|
13118
13385
|
{
|
|
@@ -13135,7 +13402,7 @@ function ActionInbox({
|
|
|
13135
13402
|
))
|
|
13136
13403
|
}
|
|
13137
13404
|
),
|
|
13138
|
-
/* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-7 px-2 text-xs", onClick: () => setShowDecided((s) => !s), children: showDecided ? "Hide decided" : "Show decided" }),
|
|
13405
|
+
view === "inbox" ? /* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-7 px-2 text-xs", onClick: () => setShowDecided((s) => !s), children: showDecided ? "Hide decided" : "Show decided" }) : null,
|
|
13139
13406
|
/* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-7 px-2 text-xs", onClick: () => void load(), children: "Refresh" })
|
|
13140
13407
|
] }),
|
|
13141
13408
|
error ? /* @__PURE__ */ jsx43(RefusalNotice, { error }) : null,
|
|
@@ -13180,7 +13447,12 @@ function ActionInbox({
|
|
|
13180
13447
|
/* @__PURE__ */ jsx43("span", { children: batchSaid }),
|
|
13181
13448
|
/* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-6 px-2", onClick: () => setBatchSaid(null), children: "Close" })
|
|
13182
13449
|
] }) : null,
|
|
13183
|
-
|
|
13450
|
+
said ? /* @__PURE__ */ jsxs38("p", { className: "flex items-center gap-2 text-xs", role: "status", "data-testid": "inbox-said", children: [
|
|
13451
|
+
/* @__PURE__ */ jsx43("span", { children: said.text }),
|
|
13452
|
+
said.undo ? /* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-6 px-2", onClick: () => void said.undo?.(), children: "Undo" }) : null,
|
|
13453
|
+
/* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-6 px-2", onClick: () => setSaid(null), children: "Close" })
|
|
13454
|
+
] }) : null,
|
|
13455
|
+
shown3.length === 0 && view === "snoozed" && !error ? /* @__PURE__ */ jsx43("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__ */ jsx43("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 ? (
|
|
13184
13456
|
// AN EMPTY INBOX SAYS WHY — and never under a refusal, where "nothing is waiting" would be
|
|
13185
13457
|
// a guess dressed as an answer.
|
|
13186
13458
|
error ? null : tableId && !everyTable && elsewhere > 0 ? /* @__PURE__ */ jsxs38("p", { className: "flex flex-wrap items-center gap-2 text-xs text-muted-foreground", "data-testid": "inbox-empty", children: [
|
|
@@ -13210,7 +13482,31 @@ function ActionInbox({
|
|
|
13210
13482
|
) : null,
|
|
13211
13483
|
/* @__PURE__ */ jsx43("ol", { className: "flex flex-col gap-1", children: group.items.map((item) => renderRow(item, shown3.indexOf(item))) })
|
|
13212
13484
|
] }, group.key)) }),
|
|
13213
|
-
/* @__PURE__ */ jsx43(
|
|
13485
|
+
view === "inbox" ? /* @__PURE__ */ jsx43(
|
|
13486
|
+
MyChecklistSteps,
|
|
13487
|
+
{
|
|
13488
|
+
className: "border-t pt-2",
|
|
13489
|
+
onlyIds: waitingIds,
|
|
13490
|
+
onSteps,
|
|
13491
|
+
actions: (stepId) => {
|
|
13492
|
+
const title = items?.find((i) => i.item_id === stepId)?.title ?? "this step";
|
|
13493
|
+
return /* @__PURE__ */ jsxs38(Fragment18, { children: [
|
|
13494
|
+
snoozing === stepId ? snoozeChoices().map((c) => /* @__PURE__ */ jsx43(
|
|
13495
|
+
Button34,
|
|
13496
|
+
{
|
|
13497
|
+
size: "sm",
|
|
13498
|
+
variant: "ghost",
|
|
13499
|
+
className: "h-5 px-1 text-[11px]",
|
|
13500
|
+
onClick: () => void snooze(stepId, title, c.until),
|
|
13501
|
+
children: c.label
|
|
13502
|
+
},
|
|
13503
|
+
c.key
|
|
13504
|
+
)) : /* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => setSnoozing(stepId), children: "Snooze" }),
|
|
13505
|
+
/* @__PURE__ */ jsx43(Button34, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void clearItem(stepId), children: "Done" })
|
|
13506
|
+
] });
|
|
13507
|
+
}
|
|
13508
|
+
}
|
|
13509
|
+
) : null
|
|
13214
13510
|
]
|
|
13215
13511
|
}
|
|
13216
13512
|
);
|
|
@@ -20841,12 +21137,15 @@ function WhereItLives({ tableId, knownOrganizationName, onMoved, variant = "head
|
|
|
20841
21137
|
expected_version: home.table.version
|
|
20842
21138
|
});
|
|
20843
21139
|
setMoving(false);
|
|
20844
|
-
setChoosing(null);
|
|
20845
21140
|
if (!moved.ok) {
|
|
20846
|
-
|
|
20847
|
-
|
|
21141
|
+
const hint = moved.error.hint?.trim();
|
|
21142
|
+
setSaid({
|
|
21143
|
+
tone: "refused",
|
|
21144
|
+
text: `Nothing moved. ${moved.error.message}${hint && !moved.error.message.includes(hint) ? ` ${hint}` : ""}`
|
|
21145
|
+
});
|
|
20848
21146
|
return;
|
|
20849
21147
|
}
|
|
21148
|
+
setChoosing(null);
|
|
20850
21149
|
setSaid({ tone: "done", text: `${moved.data.tableName} now lives in ${moved.data.to.name}.` });
|
|
20851
21150
|
setAttempt((n) => n + 1);
|
|
20852
21151
|
onMoved?.(moved.data.to);
|
|
@@ -20882,65 +21181,90 @@ function WhereItLives({ tableId, knownOrganizationName, onMoved, variant = "head
|
|
|
20882
21181
|
]
|
|
20883
21182
|
}
|
|
20884
21183
|
) }),
|
|
20885
|
-
/* @__PURE__ */ jsx73(
|
|
20886
|
-
|
|
20887
|
-
|
|
20888
|
-
|
|
20889
|
-
"
|
|
20890
|
-
|
|
20891
|
-
|
|
20892
|
-
|
|
20893
|
-
|
|
20894
|
-
|
|
20895
|
-
|
|
20896
|
-
|
|
20897
|
-
|
|
20898
|
-
|
|
20899
|
-
|
|
20900
|
-
".
|
|
20901
|
-
|
|
20902
|
-
|
|
20903
|
-
|
|
20904
|
-
|
|
20905
|
-
|
|
20906
|
-
|
|
20907
|
-
"
|
|
20908
|
-
answer.home.table.name,
|
|
20909
|
-
" to ",
|
|
20910
|
-
choosing.name,
|
|
20911
|
-
"?"
|
|
21184
|
+
/* @__PURE__ */ jsx73(
|
|
21185
|
+
PopoverContent3,
|
|
21186
|
+
{
|
|
21187
|
+
align: "start",
|
|
21188
|
+
className: "w-80 p-3 text-xs",
|
|
21189
|
+
onClick: (e) => e.stopPropagation(),
|
|
21190
|
+
onFocusOutside: (e) => e.preventDefault(),
|
|
21191
|
+
children: answer === null ? /* @__PURE__ */ jsx73("p", { className: "text-muted-foreground", children: "Asking the record store where this table lives\u2026" }) : answer.state === "not-given" ? /* @__PURE__ */ jsx73("p", { className: "text-muted-foreground", children: "This table has not been shared with you, so where it lives is not yours to see." }) : answer.state === "door-absent" || answer.state === "unavailable" ? /* @__PURE__ */ jsxs67("div", { className: "space-y-2", children: [
|
|
21192
|
+
knownOrganizationName ? /* @__PURE__ */ jsxs67("p", { children: [
|
|
21193
|
+
"Lives in ",
|
|
21194
|
+
/* @__PURE__ */ jsx73("span", { className: "font-medium text-foreground", children: knownOrganizationName }),
|
|
21195
|
+
"."
|
|
21196
|
+
] }) : null,
|
|
21197
|
+
/* @__PURE__ */ jsx73("p", { className: "text-muted-foreground", children: answer.state === "door-absent" ? "Moving it to another organization is not available on this database yet." : `The record store could not be asked where this lives, so nothing here is an answer about your access. ${answer.why}` }),
|
|
21198
|
+
answer.state === "unavailable" ? /* @__PURE__ */ jsx73(Button60, { size: "sm", variant: "outline", className: "h-7 text-xs", onClick: () => setAttempt((n) => n + 1), children: "Ask again" }) : null
|
|
21199
|
+
] }) : /* @__PURE__ */ jsxs67("div", { className: "space-y-2", "data-where-it-lives-panel": answer.home.table.id, children: [
|
|
21200
|
+
/* @__PURE__ */ jsxs67("p", { children: [
|
|
21201
|
+
/* @__PURE__ */ jsxs67("span", { className: "text-muted-foreground", children: [
|
|
21202
|
+
answer.home.table.name,
|
|
21203
|
+
" lives in "
|
|
21204
|
+
] }),
|
|
21205
|
+
/* @__PURE__ */ jsx73("span", { className: "font-medium text-foreground", children: answer.home.organization.name }),
|
|
21206
|
+
"."
|
|
20912
21207
|
] }),
|
|
20913
|
-
/* @__PURE__ */ jsx73("p", { className: "text-
|
|
20914
|
-
|
|
20915
|
-
|
|
20916
|
-
/* @__PURE__ */
|
|
21208
|
+
said && !(said.tone === "refused" && choosing) ? /* @__PURE__ */ jsx73("p", { "data-where-it-lives-said": said.tone, className: said.tone === "refused" ? "text-destructive" : "text-foreground", children: said.text }) : null,
|
|
21209
|
+
choosing ? (
|
|
21210
|
+
// THE CONSEQUENCE, SAID BEFORE THE MOVE, in the same panel — no second dialog.
|
|
21211
|
+
/* @__PURE__ */ jsxs67("div", { className: "space-y-2", "data-where-it-lives-confirm": choosing.id, children: [
|
|
21212
|
+
/* @__PURE__ */ jsxs67("p", { className: "font-medium text-foreground", children: [
|
|
21213
|
+
"Move ",
|
|
21214
|
+
answer.home.table.name,
|
|
21215
|
+
" to ",
|
|
21216
|
+
choosing.name,
|
|
21217
|
+
"?"
|
|
21218
|
+
] }),
|
|
21219
|
+
/* @__PURE__ */ jsx73("p", { className: "text-muted-foreground", children: moveConsequence(answer.home, choosing) }),
|
|
21220
|
+
said?.tone === "refused" ? /* @__PURE__ */ jsx73("p", { "data-where-it-lives-said": "refused", role: "alert", className: "text-destructive", children: said.text }) : null,
|
|
21221
|
+
/* @__PURE__ */ jsxs67("div", { className: "flex gap-2", children: [
|
|
21222
|
+
/* @__PURE__ */ jsx73(Button60, { size: "sm", className: "h-7 text-xs", disabled: moving, onClick: () => void move(choosing), children: moving ? `Moving to ${choosing.name}\u2026` : said?.tone === "refused" ? "Try again" : "Move it" }),
|
|
21223
|
+
/* @__PURE__ */ jsx73(
|
|
21224
|
+
Button60,
|
|
21225
|
+
{
|
|
21226
|
+
size: "sm",
|
|
21227
|
+
variant: "ghost",
|
|
21228
|
+
className: "h-7 text-xs",
|
|
21229
|
+
disabled: moving,
|
|
21230
|
+
onClick: () => {
|
|
21231
|
+
const wasRefused = said?.tone === "refused";
|
|
21232
|
+
setChoosing(null);
|
|
21233
|
+
setSaid(null);
|
|
21234
|
+
if (wasRefused) setAttempt((n) => n + 1);
|
|
21235
|
+
},
|
|
21236
|
+
children: "Cancel"
|
|
21237
|
+
}
|
|
21238
|
+
)
|
|
21239
|
+
] })
|
|
21240
|
+
] })
|
|
21241
|
+
) : !answer.home.mayMove ? /* @__PURE__ */ jsx73("p", { className: "text-muted-foreground", children: answer.home.whyNot }) : answer.home.heldBy.length > 0 ? /* @__PURE__ */ jsxs67("div", { className: "space-y-1", children: [
|
|
21242
|
+
/* @__PURE__ */ jsx73("p", { className: "font-medium text-foreground", children: "It cannot move yet:" }),
|
|
21243
|
+
/* @__PURE__ */ jsx73("ul", { className: "list-disc space-y-1 pl-4 text-muted-foreground", children: answer.home.heldBy.map((line) => /* @__PURE__ */ jsx73("li", { children: line }, line)) })
|
|
21244
|
+
] }) : answer.home.destinations.length === 0 ? /* @__PURE__ */ jsx73("p", { className: "text-muted-foreground", children: "You are not a member of any other organization, so there is nowhere else to move it." }) : /* @__PURE__ */ jsxs67("div", { className: "space-y-1", children: [
|
|
21245
|
+
/* @__PURE__ */ jsx73("p", { className: "font-medium text-foreground", children: "Move it to" }),
|
|
21246
|
+
/* @__PURE__ */ jsx73("ul", { className: "max-h-64 space-y-1 overflow-y-auto pr-1", children: answer.home.destinations.map((to) => /* @__PURE__ */ jsx73("li", { children: to.ok ? /* @__PURE__ */ jsx73(
|
|
21247
|
+
Button60,
|
|
21248
|
+
{
|
|
21249
|
+
size: "sm",
|
|
21250
|
+
variant: "outline",
|
|
21251
|
+
className: "h-7 w-full justify-start text-xs",
|
|
21252
|
+
"data-where-it-lives-move": to.id,
|
|
21253
|
+
onClick: () => {
|
|
21254
|
+
setSaid(null);
|
|
21255
|
+
setChoosing(to);
|
|
21256
|
+
},
|
|
21257
|
+
children: to.name
|
|
21258
|
+
}
|
|
21259
|
+
) : /* @__PURE__ */ jsxs67("p", { className: "text-muted-foreground", children: [
|
|
21260
|
+
/* @__PURE__ */ jsx73("span", { className: "text-foreground", children: to.name }),
|
|
21261
|
+
" \u2014 ",
|
|
21262
|
+
to.why
|
|
21263
|
+
] }) }, to.id)) })
|
|
20917
21264
|
] })
|
|
20918
21265
|
] })
|
|
20919
|
-
|
|
20920
|
-
|
|
20921
|
-
/* @__PURE__ */ jsx73("ul", { className: "list-disc space-y-1 pl-4 text-muted-foreground", children: answer.home.heldBy.map((line) => /* @__PURE__ */ jsx73("li", { children: line }, line)) })
|
|
20922
|
-
] }) : answer.home.destinations.length === 0 ? /* @__PURE__ */ jsx73("p", { className: "text-muted-foreground", children: "You are not a member of any other organization, so there is nowhere else to move it." }) : /* @__PURE__ */ jsxs67("div", { className: "space-y-1", children: [
|
|
20923
|
-
/* @__PURE__ */ jsx73("p", { className: "font-medium text-foreground", children: "Move it to" }),
|
|
20924
|
-
/* @__PURE__ */ jsx73("ul", { className: "max-h-64 space-y-1 overflow-y-auto pr-1", children: answer.home.destinations.map((to) => /* @__PURE__ */ jsx73("li", { children: to.ok ? /* @__PURE__ */ jsx73(
|
|
20925
|
-
Button60,
|
|
20926
|
-
{
|
|
20927
|
-
size: "sm",
|
|
20928
|
-
variant: "outline",
|
|
20929
|
-
className: "h-7 w-full justify-start text-xs",
|
|
20930
|
-
"data-where-it-lives-move": to.id,
|
|
20931
|
-
onClick: () => {
|
|
20932
|
-
setSaid(null);
|
|
20933
|
-
setChoosing(to);
|
|
20934
|
-
},
|
|
20935
|
-
children: to.name
|
|
20936
|
-
}
|
|
20937
|
-
) : /* @__PURE__ */ jsxs67("p", { className: "text-muted-foreground", children: [
|
|
20938
|
-
/* @__PURE__ */ jsx73("span", { className: "text-foreground", children: to.name }),
|
|
20939
|
-
" \u2014 ",
|
|
20940
|
-
to.why
|
|
20941
|
-
] }) }, to.id)) })
|
|
20942
|
-
] })
|
|
20943
|
-
] }) })
|
|
21266
|
+
}
|
|
21267
|
+
)
|
|
20944
21268
|
]
|
|
20945
21269
|
}
|
|
20946
21270
|
);
|
|
@@ -22074,6 +22398,7 @@ export {
|
|
|
22074
22398
|
GridCell,
|
|
22075
22399
|
HistoryPanel,
|
|
22076
22400
|
INBOX_GROUPINGS,
|
|
22401
|
+
INBOX_VIEWS,
|
|
22077
22402
|
IN_MEMORY_QUEUE_REASON,
|
|
22078
22403
|
ImportWizard,
|
|
22079
22404
|
KERNEL_REASON,
|
|
@@ -22284,6 +22609,7 @@ export {
|
|
|
22284
22609
|
scalarText,
|
|
22285
22610
|
seedIsSatisfied,
|
|
22286
22611
|
shareUnavailableReason,
|
|
22612
|
+
snoozeChoices,
|
|
22287
22613
|
specFromBlock,
|
|
22288
22614
|
storeDecidesRights,
|
|
22289
22615
|
styleFromDecorations,
|