@remit/web-client 0.0.171 → 0.0.172
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remit/web-client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.172",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Remit web client, published as composable primitives — the app shell, auth shells, and runtime config. A distributor imports what it composes and bundles it.",
|
|
6
6
|
"exports": {
|
|
@@ -59,7 +59,12 @@ export const ComposeProvider = ({
|
|
|
59
59
|
enabled: !!pollingMessageId,
|
|
60
60
|
refetchInterval: (query) => {
|
|
61
61
|
const status = query.state.data?.status;
|
|
62
|
-
if (
|
|
62
|
+
if (
|
|
63
|
+
status === "sent" ||
|
|
64
|
+
status === "unfiled" ||
|
|
65
|
+
status === "failed" ||
|
|
66
|
+
status === "blocked"
|
|
67
|
+
)
|
|
63
68
|
return false;
|
|
64
69
|
if (Date.now() - startedAtRef.current > MAX_POLL_DURATION_MS)
|
|
65
70
|
return false;
|
|
@@ -72,6 +77,7 @@ export const ComposeProvider = ({
|
|
|
72
77
|
|
|
73
78
|
const terminal =
|
|
74
79
|
polledMessage.status === "sent" ||
|
|
80
|
+
polledMessage.status === "unfiled" ||
|
|
75
81
|
polledMessage.status === "failed" ||
|
|
76
82
|
polledMessage.status === "blocked";
|
|
77
83
|
|
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
matchesOutboxSearch,
|
|
60
60
|
outboxQueryIsUnsupported,
|
|
61
61
|
} from "@/lib/outbox-search";
|
|
62
|
-
import { isOutboxListRow,
|
|
62
|
+
import { isOutboxListRow, showsLastError } from "@/lib/outbox-status";
|
|
63
63
|
import { normalizeSearchQuery } from "@/lib/search-query";
|
|
64
64
|
import { parseSearchTokens } from "@/lib/search-tokens";
|
|
65
65
|
import { useEditDraft, useRetainOpenPanels } from "@/routing";
|
|
@@ -87,6 +87,11 @@ const STATUS_CONFIG: Record<
|
|
|
87
87
|
label: "Sent",
|
|
88
88
|
className: "text-positive",
|
|
89
89
|
},
|
|
90
|
+
unfiled: {
|
|
91
|
+
icon: AlertTriangle,
|
|
92
|
+
label: "Sent, not filed",
|
|
93
|
+
className: "text-warning",
|
|
94
|
+
},
|
|
90
95
|
failed: {
|
|
91
96
|
icon: AlertCircle,
|
|
92
97
|
label: "Failed",
|
|
@@ -310,7 +315,7 @@ function OutboxMessageRow({
|
|
|
310
315
|
>;
|
|
311
316
|
if (!STATUS_CONFIG[status]) return null;
|
|
312
317
|
|
|
313
|
-
const showError =
|
|
318
|
+
const showError = showsLastError(message.status);
|
|
314
319
|
|
|
315
320
|
return (
|
|
316
321
|
<OutboxRow
|
|
@@ -414,7 +419,7 @@ function OutboxMessageDetail({ message, onBack }: OutboxMessageDetailProps) {
|
|
|
414
419
|
<span className={cn("text-xs font-medium", config.className)}>
|
|
415
420
|
{config.label}
|
|
416
421
|
</span>
|
|
417
|
-
{
|
|
422
|
+
{showsLastError(message.status) && message.lastError && (
|
|
418
423
|
<span className="text-xs text-fg-muted">
|
|
419
424
|
— {message.lastError}
|
|
420
425
|
</span>
|
|
@@ -3,7 +3,7 @@ import { describe, test } from "node:test";
|
|
|
3
3
|
import {
|
|
4
4
|
describeOutboxStatus,
|
|
5
5
|
isOutboxListRow,
|
|
6
|
-
|
|
6
|
+
showsLastError,
|
|
7
7
|
} from "./outbox-status.js";
|
|
8
8
|
|
|
9
9
|
describe("describeOutboxStatus", () => {
|
|
@@ -25,6 +25,13 @@ describe("describeOutboxStatus", () => {
|
|
|
25
25
|
assert.equal(desc.label, "Sent");
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
+
test("unfiled says the message was sent but not filed", () => {
|
|
29
|
+
const desc = describeOutboxStatus("unfiled");
|
|
30
|
+
assert.ok(desc);
|
|
31
|
+
assert.equal(desc.tone, "warning");
|
|
32
|
+
assert.match(desc.label, /not filed/);
|
|
33
|
+
});
|
|
34
|
+
|
|
28
35
|
test("failed is error tone (distinct from blocked)", () => {
|
|
29
36
|
const desc = describeOutboxStatus("failed");
|
|
30
37
|
assert.ok(desc);
|
|
@@ -33,19 +40,23 @@ describe("describeOutboxStatus", () => {
|
|
|
33
40
|
});
|
|
34
41
|
});
|
|
35
42
|
|
|
36
|
-
describe("
|
|
37
|
-
test("sent must NOT
|
|
38
|
-
assert.equal(
|
|
43
|
+
describe("showsLastError", () => {
|
|
44
|
+
test("sent must NOT surface an error — never show an error subtitle on success (issue #192)", () => {
|
|
45
|
+
assert.equal(showsLastError("sent"), false);
|
|
39
46
|
});
|
|
40
47
|
|
|
41
|
-
test("failed and blocked
|
|
42
|
-
assert.equal(
|
|
43
|
-
assert.equal(
|
|
48
|
+
test("failed and blocked surface their error", () => {
|
|
49
|
+
assert.equal(showsLastError("failed"), true);
|
|
50
|
+
assert.equal(showsLastError("blocked"), true);
|
|
44
51
|
});
|
|
45
52
|
|
|
46
|
-
test("
|
|
47
|
-
assert.equal(
|
|
48
|
-
|
|
53
|
+
test("unfiled surfaces its reason — the row exists only to carry it", () => {
|
|
54
|
+
assert.equal(showsLastError("unfiled"), true);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("queued and sending carry no error", () => {
|
|
58
|
+
assert.equal(showsLastError("queued"), false);
|
|
59
|
+
assert.equal(showsLastError("sending"), false);
|
|
49
60
|
});
|
|
50
61
|
});
|
|
51
62
|
|
|
@@ -61,4 +72,8 @@ describe("isOutboxListRow", () => {
|
|
|
61
72
|
assert.equal(isOutboxListRow("failed"), true);
|
|
62
73
|
assert.equal(isOutboxListRow("blocked"), true);
|
|
63
74
|
});
|
|
75
|
+
|
|
76
|
+
test("keeps an unfiled row listed — it is the only copy the user has", () => {
|
|
77
|
+
assert.equal(isOutboxListRow("unfiled"), true);
|
|
78
|
+
});
|
|
64
79
|
});
|
package/src/lib/outbox-status.ts
CHANGED
|
@@ -29,6 +29,7 @@ const STATUS_DESCRIPTORS: Record<OutboxDisplayStatus, OutboxStatusDescriptor> =
|
|
|
29
29
|
queued: { label: "Queued", tone: "neutral" },
|
|
30
30
|
sending: { label: "Sending…", tone: "info" },
|
|
31
31
|
sent: { label: "Sent", tone: "success" },
|
|
32
|
+
unfiled: { label: "Sent, not filed", tone: "warning" },
|
|
32
33
|
failed: { label: "Failed", tone: "error" },
|
|
33
34
|
blocked: { label: "Blocked", tone: "warning" },
|
|
34
35
|
};
|
|
@@ -56,11 +57,12 @@ export const describeOutboxStatus = (
|
|
|
56
57
|
*
|
|
57
58
|
* Critically: `sent` is NOT included. A successful send must never display
|
|
58
59
|
* a stale lastError — that is the contradictory "green check + 'SMTP not
|
|
59
|
-
* configured'" UI bug from issue #192.
|
|
60
|
+
* configured'" UI bug from issue #192. `unfiled` is: the message was
|
|
61
|
+
* delivered but could not be filed, and the reason is the whole point of
|
|
62
|
+
* the row still being there.
|
|
60
63
|
*/
|
|
61
|
-
export const
|
|
62
|
-
status
|
|
63
|
-
): boolean => status === "failed" || status === "blocked";
|
|
64
|
+
export const showsLastError = (status: RemitImapOutboxMessageStatus): boolean =>
|
|
65
|
+
status === "failed" || status === "blocked" || status === "unfiled";
|
|
64
66
|
|
|
65
67
|
/**
|
|
66
68
|
* Whether the outbox list view should render this row.
|
|
@@ -68,7 +70,9 @@ export const isUnsendableStatus = (
|
|
|
68
70
|
* `draft` belongs in the Drafts view. `sent` rows are deleted by the IMAP
|
|
69
71
|
* APPEND handler (issue #178) — but until that happens we hide them from
|
|
70
72
|
* the Outbox list so a successfully-sent message never appears in two
|
|
71
|
-
* places at once (issue #193).
|
|
73
|
+
* places at once (issue #193). `unfiled` is the settled failure of that
|
|
74
|
+
* APPEND: the message is on no server folder, so the Outbox row is the only
|
|
75
|
+
* copy the user has and it stays listed.
|
|
72
76
|
*/
|
|
73
77
|
export const isOutboxListRow = (
|
|
74
78
|
status: RemitImapOutboxMessageStatus,
|