@aiquants/daily-report 0.47.1 → 0.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/README.md +59 -42
- package/dist/client.d.mts +13 -5
- package/dist/client.d.ts +13 -5
- package/dist/client.js +5 -5
- package/dist/client.mjs +5 -5
- package/dist/server.js +1 -1
- package/dist/server.mjs +1 -1
- package/dist/styles/daily-report.standalone.css +1 -1
- package/package.json +8 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,67 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@aiquants/daily-report` are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.49.0 (2026-10-21)
|
|
6
|
+
|
|
7
|
+
### Breaking
|
|
8
|
+
|
|
9
|
+
- **`DailyReportPage` の `sessionEpoch` は必須**: ホストが失効の後に同じ利用者で確かめたセッションの数 (0 以上の安全な整数)。欠けると描画時に
|
|
10
|
+
`TypeError`、ほかの値は `RangeError`。失効で読み直すホストは定数 (`0` など) を渡せば、これまでと同じに動く。
|
|
11
|
+
- **`DailyReportErrorInfo` は `reason: "failed" | "refused"` を持ち、`operation` は `"liveUpdates"` も取る**: 403 (権限の断り) とライブ更新の
|
|
12
|
+
`forbidden` の終わりは `refused`、ほかは `failed`。`operation` を網羅して分けるホストは `"liveUpdates"` を足す。
|
|
13
|
+
- **検索・絞り込み・印のフックと置き場の options から `onSessionExpired` を外した**: `useDailyReportSearch`・`useDailyReportSearchFacets`・
|
|
14
|
+
`useShownSearchMarksStore`・`createDailyReportSearchSession`・`createDailyReportSearchMarksStore` は、セッションの終わりを API の基点の
|
|
15
|
+
セッションの門へ知らせる (下)。公開の `useDailyReportSseConnection` は `onSessionEnded` と `onRefused` を必須で受ける。
|
|
16
|
+
- **`DailyReportSearchFailure` に `refused` を足した** (403)。
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **セッションの終わりで読み直さずに止め、ホストが確かめたら続ける (WCAG 2.2.5 Re-authenticating)**: どの読み取り (ids の流れ・詳細・検索・
|
|
21
|
+
絞り込み・印) か書き込みが 401 で答えるか、SSE が `auth-required` で終わると、パッケージは API の基点ごとのセッションの門で通信を止め、
|
|
22
|
+
`config.onSessionExpired` を止めるたびに 1 回だけ呼ぶ (これまでは場所ごとに、1 回の失効で何度も呼びえた)。読み取りは中断し、SSE は閉じ、
|
|
23
|
+
ids の流れ・詳細・検索は新しい要求を出さず、書き込みは送らない (何も送らずに拒み、コメントの欄は下書きを残す)。下書き・開いた編集の形・
|
|
24
|
+
選択・検索・スクロールはメモリに残る。`sessionEpoch` が止めた時の値と違えば続ける: ids の流れは続きを読み (完走したことのある一覧は
|
|
25
|
+
読み直す)、SSE はカーソルから開き直し、待たせた詳細と絞り込みの候補を読み、検索と印を頼み直す。書き込みは送り直さない。続ける前に送った
|
|
26
|
+
要求の 401 は、その後のセッションを止めない。一度完走した一覧は、止めても本体を外さない (選択・検索・スクロールが残る)。
|
|
27
|
+
- **ラベル `operationRefused` (関数) と `liveUpdatesRefused`**: 断られた書き込みと、断られたライブ更新の知らせの文言。固有のキーは 116
|
|
28
|
+
(文字列 92 → 93・関数 22 → 23) になる。ログのチャンネル `SessionGate` (クライアントのチャンネルは 5 つ)。
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **書き込みの 401 がセッションの終わりを知らせなかった**: 8 つの書き込みは 401 で汎用の「操作に失敗」を出すだけだった。いまは門を止めて
|
|
33
|
+
`onSessionExpired` を 1 回呼び、パッケージの誤りの知らせは出さない (ホストの知らせが伝える)。
|
|
34
|
+
- **403 を失効として扱っていた**: ids の流れ・検索・絞り込み・印は 403 で `onSessionExpired` を呼び、詳細の置き場は 403 を失効の断りとして
|
|
35
|
+
扱っていた。403 は権限の断りで、サインインし直しても変わらない: 書き込みは `labels.operationRefused` の知らせ (`reason: "refused"`)、
|
|
36
|
+
検索と絞り込みは `refused`、詳細は断りを記録の誤りとして分け合い、印は付けず、ids の流れはやり直さずに `failed` で止まる。どれもホストの
|
|
37
|
+
再認証を求めない。
|
|
38
|
+
- **SSE の `forbidden` が記録だけだった**: ライブ更新が止まったことを読み手が知れるよう、断りとして知らせの口へ出す
|
|
39
|
+
(`operation: "liveUpdates"`, `reason: "refused"`, `labels.liveUpdatesRefused`)。
|
|
40
|
+
|
|
41
|
+
## 0.48.0 (2026-10-21)
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
|
|
45
|
+
- **一覧と詳細ペインの境界の取っ手は、クリックで決まった幅を順に切り替える (WCAG 2.5.7 Dragging Movements)**: `@aiquants/resize-panels` 2.2.0 の
|
|
46
|
+
`activationSizes` へ一覧のパネルの最小・既定・最大の幅 (160・360・520px) を渡すので、ドラッグの閾値に届かないクリックかタップが一覧の幅を次の止まり先へ
|
|
47
|
+
進める (最後の後は最初へ)。resize-panels のピアの下限は 2.2.0。
|
|
48
|
+
- **ラベル `resizeHandleHint`**: 取っ手のツールチップ (`title`) の文言。これまでのツールチップは resize-panels の英語の既定の名前で、`locale: "ja"` でも
|
|
49
|
+
英語だった。固有のキーは 114 になる。
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- **ラベルのカタログのエンジンのキーは、組み込む `@aiquants/virtualscroll` のキーに従う**: スクロールバーの値を持つ要素を `role="scrollbar"` の
|
|
54
|
+
トラック 1 つにした `@aiquants/virtualscroll` の版は、つまみが名前を持たなくなったので、カタログから `verticalScrollThumb` /
|
|
55
|
+
`horizontalScrollThumb` を外した。日報のカタログはエンジンのキー (`VIRTUAL_SCROLL_LABEL_KEYS`) を値で再利用するので、その版の上では
|
|
56
|
+
`DAILY_REPORT_LABEL_KEYS` からも 2 キーが減り (エンジン 9。固有のキーは下の `resizeHandleHint` を足して 114)、`config.labels` にその 2 キーを渡すと未知のキーとして描画時に
|
|
57
|
+
`RangeError` になる。両ビューのバーはこれまでどおりポインター専用で支援技術から隠れ、隠れたバーの `role="scrollbar"` の要素が
|
|
58
|
+
`verticalScrollBar` の名前を持つ。README と設計仕様書は、エンジンのキーの件数を書き写さない形に改めた。
|
|
59
|
+
|
|
60
|
+
### Tests
|
|
61
|
+
|
|
62
|
+
- `report-views.scroll-bar-a11y.spec.tsx` と `virtual-scroll-stand-in.conformance.spec.tsx` は、本物のバーを包み (`data-aqvs-scrollbar`) と、その
|
|
63
|
+
中の `role="scrollbar"` の要素で引く (矢印は `role="scrollbar"` の要素の兄弟になった)。バーと矢印の押下に加えて、`role="scrollbar"` の要素の
|
|
64
|
+
押下も既定動作を取り消すことを確かめる。
|
|
65
|
+
|
|
5
66
|
## 0.47.1 (2026-10-16)
|
|
6
67
|
|
|
7
68
|
版番号は 0.47.1 (patch) とする: 公開の名前を 1 つ足すだけで、振る舞いは変えない。
|
package/README.md
CHANGED
|
@@ -101,7 +101,7 @@ keyboard themselves; see [Keyboard, focus and selection](#keyboard-focus-and-sel
|
|
|
101
101
|
own parts under `prefers-reduced-motion: reduce` (3.8.2;
|
|
102
102
|
see [Selection and focus appearance](#selection-and-focus-appearance)); and both views re-record their scroll anchor from its `onScrollAdjust`
|
|
103
103
|
notification and rely on its edge-keeping snap (3.9.0; see **Host selections and list changes** and [View height](#view-height-host-layout)). The
|
|
104
|
-
label catalog reuses its
|
|
104
|
+
label catalog reuses its engine keys (every label key `@aiquants/virtualscroll` exports), the name of the scroll bar among them (3.10.0; see
|
|
105
105
|
[Localization](#localization-locale--labels)).
|
|
106
106
|
`DailyReportRevealOptions`, the options of the test handle's `revealIndex`, is `@aiquants/virtualscroll`'s `scrollToIndex` options type, which takes
|
|
107
107
|
`align: "nearest"` since 3.11.0, and DetailList rows stay at the tree's tops and heights after a batch of re-measurements whose deltas cancel only
|
|
@@ -660,11 +660,12 @@ its payload — with one strict parser each, after authentication and before any
|
|
|
660
660
|
| `[DailyReportSseReader]` | `info` | the shared SSE reader's Redis errors |
|
|
661
661
|
| `[DailyReportExternalSource]` | `info` | `transformJsonArray`'s malformed JSON columns of an external source |
|
|
662
662
|
|
|
663
|
-
The client has no host logger port: its
|
|
663
|
+
The client has no host logger port: its five channels of the same list write to the console from `info` — `[DailyReportActionProvider]` (the action
|
|
664
664
|
provider: a failed action, the queue of SSE messages about uncached reports, a cache reload), `[DailyReportDetailLoader]` (the detail loading: a
|
|
665
665
|
stale update of a report's cache, a failed prefetch of a business date, a failed refetch that left the shown report in place),
|
|
666
666
|
`[DailyReportIdsStream]` (the ids stream client: a revalidation that gave up, a rejected malformed line, which ends the attempt, a skipped line of
|
|
667
|
-
an unknown kind, a malformed stream anchor)
|
|
667
|
+
an unknown kind, a malformed stream anchor), `[DailyReportSseConnection]` (the SSE connection hook) and `[DailyReportSessionGate]` (the session
|
|
668
|
+
gate: a pause because the viewer's session ended, and the resume).
|
|
668
669
|
Every line, the server's and the client's, carries exactly one channel prefix: no message spells a `[DailyReport…]` prefix of its own.
|
|
669
670
|
|
|
670
671
|
A 500 is one line: its message (`500 endpoint=<name> elapsed=<ms>ms name=<error name> code=<code or N/A> message=<message>`,
|
|
@@ -1741,8 +1742,8 @@ unexpected error, a request that is not the package's client (another origin's p
|
|
|
1741
1742
|
|
|
1742
1743
|
| Server-side situation | Response | Client (`useDailyReportSseConnection`) |
|
|
1743
1744
|
| --- | --- | --- |
|
|
1744
|
-
| Not authenticated | 200, `retry: 86400000` → `event: auth-required` (`Set-Cookie` forwarded) | terminated;
|
|
1745
|
-
| Authenticated but no internal user | 200, `retry: 86400000` → `event: forbidden` | terminated; no navigation (a reload cannot fix it); visible through `sseStatus` |
|
|
1745
|
+
| Not authenticated | 200, `retry: 86400000` → `event: auth-required` (`Set-Cookie` forwarded) | terminated; pauses the package (`config.onSessionExpired()` once) and reconnects from its cursor when `sessionEpoch` changes |
|
|
1746
|
+
| Authenticated but no internal user | 200, `retry: 86400000` → `event: forbidden` | terminated; no navigation (a reload cannot fix it); reported as a refusal through the error surface (`operation: "liveUpdates"`, `reason: "refused"`, `labels.liveUpdatesRefused`) and visible through `sseStatus` |
|
|
1746
1747
|
| A request from another origin's page that the isolation refuses ([Request isolation](#request-isolation)) | 403 JSON before authentication (`Cache-Control: no-store`, the routes' security headers, no `Set-Cookie`), counted in the bounded refusal record | never met: the package's client connects from the page's own origin |
|
|
1747
1748
|
| A React Router single-fetch data request (`<path>.data`, `GET` or `HEAD`) | 404 JSON before authentication (`{"error":{"message":"Not Found"}}`, `Cache-Control: no-store`, the routes' security headers, no `Set-Cookie`), with no subscription or timer and no line in the refusal record ([Request isolation](#request-isolation)) | never sent by the client: `EventSource` requests the route itself |
|
|
1748
1749
|
| Unknown endpoint | 404 | treated as retryable; backoff up to 30 s |
|
|
@@ -2301,8 +2302,8 @@ The remainder does not go between a caption and its control: at q = 8 that gap w
|
|
|
2301
2302
|
Each request is sent `cache: "no-cache"`: the browser revalidates its previous answer with the ETag (`If-None-Match`) and, on a 304, hands over its
|
|
2302
2303
|
cached 200, so an unchanged answer's body is not sent again.
|
|
2303
2304
|
A failed first load shows only the status line and is retried at the next opening; a failed reload keeps the previous candidates and shows the
|
|
2304
|
-
failure in the status line. 401
|
|
2305
|
-
included, `failed`.
|
|
2305
|
+
failure in the status line. A 401 pauses the package at the session's end (see [Client wiring](#client-wiring)) and loads the candidates again
|
|
2306
|
+
when it resumes; a 403 shows `refused`, 404 `unavailable`, 429 `busy`, and anything else, a malformed answer included, `failed`.
|
|
2306
2307
|
The cells render once the candidates are loaded. The author and customer options are sorted with `Intl.Collator(config.locale)` (values the
|
|
2307
2308
|
collation ties are ordered by UTF-16 code units) and labelled with their value; the source-type options keep the server's order and are labelled
|
|
2308
2309
|
with their badge label from `sourceTypeConfigs` (the source type itself without one).
|
|
@@ -2426,13 +2427,13 @@ While an answer shows, the List cards, the side pane and the DetailList rows mar
|
|
|
2426
2427
|
A field is painted only when its marks were computed on the value drawn (the fingerprint): after a save or an SSE update the old ranges are not
|
|
2427
2428
|
painted and the field asks once for fresh marks. An answer whose `wordsDigest` differs from the shown answer's words is dropped; a quiet re-query of
|
|
2428
2429
|
the same search makes the marks stale and the mounted rows ask again;
|
|
2429
|
-
401 and 403
|
|
2430
|
+
a 401 pauses the package at the session's end (the marks are asked again when it resumes) and a 403 leaves the rows plain; a 429 whose `Retry-After` is at most 60 s (one window of the server's rate bucket) is asked again once, after
|
|
2430
2431
|
that delay, for the reports still subscribed then (one whose subscribers left meanwhile asks again when it is subscribed again), and a 429 without a
|
|
2431
2432
|
`Retry-After`, or with a longer one, sets no timer and leaves its reports plain for the answer's epoch (a delay of 2^31 ms or more would overflow
|
|
2432
2433
|
the timer and ask again at once);
|
|
2433
2434
|
any other failure of the request — a network failure, an abort, another status, a body that is not JSON — leaves those rows plain for as long as the
|
|
2434
2435
|
shown answer stays the same and reports nothing.
|
|
2435
|
-
Only the request's own failures are dropped: an error thrown by the host's `onSessionExpired
|
|
2436
|
+
Only the request's own failures are dropped: an error thrown by the session report (the host's `onSessionExpired`), by holding a 429's retry or by applying an answer and
|
|
2436
2437
|
notifying the rows rejects the batch, and the scheduler reports it with `reportError` (the window's `error` event, where a host's error monitoring
|
|
2437
2438
|
sees it) after it has freed the request's slot; a batch that rejects with its own abort's reason reports nothing.
|
|
2438
2439
|
Disposing the store — a new search, or React hiding the screen inside an `<Activity>` — aborts its requests, cancels its retry timers and gives
|
|
@@ -2487,13 +2488,15 @@ export const clientLoader = createDailyReportClientLoader() // Bootstraps the
|
|
|
2487
2488
|
|
|
2488
2489
|
export default function Route() {
|
|
2489
2490
|
const { user, userId } = useLoaderData<typeof clientLoader>()
|
|
2491
|
+
const { sessionEpoch, showSignInNotice } = useYourReauthentication(user) // Your notice, sign-in window and same-user check
|
|
2490
2492
|
return (
|
|
2491
2493
|
<YourAppLayout>
|
|
2492
2494
|
<DailyReportPage
|
|
2493
2495
|
user={user}
|
|
2494
2496
|
userId={userId}
|
|
2497
|
+
sessionEpoch={sessionEpoch} // Required: advance it when the same user has signed in again (the package resumes)
|
|
2495
2498
|
config={{
|
|
2496
|
-
onSessionExpired:
|
|
2499
|
+
onSessionExpired: showSignInNotice, // Required: called once each time the package pauses at a session end
|
|
2497
2500
|
renderHeader: ({ title, annotation }) => <YourHeader title={title} annotation={annotation} />,
|
|
2498
2501
|
showDevControls: import.meta.env.DEV, // Toggle SSE subscriptions, etc.
|
|
2499
2502
|
locale: "en", // UI chrome language: "en" (default) | "ja"
|
|
@@ -2519,10 +2522,20 @@ one definition of a draft (`draftLabelNames` in [DI ports](#di-ports)), so `conf
|
|
|
2519
2522
|
unknown key.
|
|
2520
2523
|
An optimistic report the viewer creates is a draft with no labels until the server's answer brings its labels (the draft label among them); an
|
|
2521
2524
|
optimistic publish clears `isDraft` at once and keeps the labels until the answer, and a failed publish restores `isDraft`.
|
|
2522
|
-
The package never navigates by itself
|
|
2523
|
-
the filters' candidates (`search-facets`)
|
|
2524
|
-
calls `onSessionExpired()`
|
|
2525
|
-
|
|
2525
|
+
The package never navigates or reloads by itself. When the viewer's session ends — the SSE stream ends with `auth-required`, or the ids stream, a
|
|
2526
|
+
detail read, a `search` request, the filters' candidates (`search-facets`), the marks (`search-marks`) or a write answers 401 — it **pauses** its
|
|
2527
|
+
network activity and calls `onSessionExpired()` once per pause: in-flight reads are aborted, the SSE connection closes, the ids stream, the detail
|
|
2528
|
+
reads and the search requests stop, no new request starts, and a write is not sent at all (it rejects without touching the server or the view; a
|
|
2529
|
+
comment field keeps its draft). Everything the page holds in memory stays: comment drafts, an open edit form, the selection, the search and the scroll.
|
|
2530
|
+
The package resumes when the page's required `sessionEpoch` prop (a safe integer >= 0; a missing one throws a `TypeError` at render and any other
|
|
2531
|
+
value a `RangeError`) differs from the value it paused at: the ids stream continues, the SSE reconnects from its cursor, held detail reads and the
|
|
2532
|
+
filters' candidates load again, and the search and the marks are asked again. Nothing is sent again on the viewer's behalf. A request sent before a
|
|
2533
|
+
resume whose 401 arrives after it does not pause the session that followed. A 403 is a refusal of the viewer, never a session end: a write answered 403
|
|
2534
|
+
is reported through the error surface with `reason: "refused"` and `labels.operationRefused(operation)`, the live updates ending with `forbidden`
|
|
2535
|
+
are reported the same way (`operation: "liveUpdates"`, `labels.liveUpdatesRefused`), a search or the filters show `refused`, a detail read keeps the
|
|
2536
|
+
refusal as the record's error, the marks stay plain, and the ids stream fails without retrying.
|
|
2537
|
+
A host that re-authenticates without a reload shows its own notice from `onSessionExpired`, lets the viewer sign in again (in another window, say), checks
|
|
2538
|
+
that the same user signed in, and then advances `sessionEpoch`; a host that reloads instead passes a constant and navigates from `onSessionExpired`.
|
|
2526
2539
|
`DailyReportConfigProvider` takes the same required `config`, and every component and hook of the package that reads the configuration needs it above:
|
|
2527
2540
|
outside it `useDailyReportConfig` throws at render (`[daily-report] useDailyReportConfig must be used within a DailyReportConfigProvider`); no default
|
|
2528
2541
|
configuration renders silently.
|
|
@@ -2554,16 +2567,18 @@ inside its TTL is not fetched. A refetch of a shown report that fails (the re-va
|
|
|
2554
2567
|
leaves the report in place with no error and only logs a warning on `[DailyReportDetailLoader]`, so the next new reader re-validates again. A settled
|
|
2555
2568
|
load error is not shared either: a reader that subscribes to a record holding an error — a row that mounts, an id that enters the input lead's band,
|
|
2556
2569
|
the side pane — asks again, and the answer replaces the error. Only a new subscription asks again or re-validates (a re-render or a second
|
|
2557
|
-
subscription of the same listener does not, so a row that keeps showing a failure or an expired report never loops), and a refusal of
|
|
2558
|
-
|
|
2559
|
-
|
|
2570
|
+
subscription of the same listener does not, so a row that keeps showing a failure or an expired report never loops), and a refusal of this read to
|
|
2571
|
+
the viewer (403, which signing in again does not change) is shared like an answer: it becomes the record's error even over a shown report, and no new
|
|
2572
|
+
reader asks again or re-validates. A session end (401) is not an error: the record keeps what it shows, the package pauses (see
|
|
2573
|
+
[Client wiring](#client-wiring)), no load starts while it is paused, and the held reports are asked again when it resumes.
|
|
2560
2574
|
The first load of a report that is not cached starts inside its first reader's subscription, with no task between the row's mount and its request,
|
|
2561
2575
|
so a held arrow key's stream of keydowns cannot postpone it until the key is released; only the refetch of an expired cached report waits 120 ms, to
|
|
2562
2576
|
absorb rows that only scroll past. Loads of reports of one business date share one request.
|
|
2563
2577
|
|
|
2564
2578
|
Mutation failures (save / publish / delete / comment) are surfaced through an error seam: inject `config.onError(info: DailyReportErrorInfo)` to route
|
|
2565
2579
|
them into your own toast/notification system, or omit it to use the package's built-in notice. Failures on a continuation that resolves after a
|
|
2566
|
-
no-reload user switch are suppressed
|
|
2580
|
+
no-reload user switch are suppressed, and so is a write answered 401 (the package pauses at the session's end and the host's notice speaks) or refused
|
|
2581
|
+
while the package is paused (nothing was sent). A write answered 403 is a refusal (`reason: "refused"`), which trying again does not change.
|
|
2567
2582
|
Deleting a report or a comment that the server no longer has (404) counts as done: the row or the comment stays removed and nothing is shown. Only the
|
|
2568
2583
|
deleting intents, `delete` and `deleteComment`, read a 404 so (their callbacks must say what a 404 means, `onGone`, and no other intent's callbacks
|
|
2569
2584
|
may, by type: `ActionCallbacks`); the 404 of any other intent rolls back and is reported.
|
|
@@ -2951,10 +2966,10 @@ the resize handle and the side pane lie outside the list.
|
|
|
2951
2966
|
`enableArrowButtonTabStops: false`, `@aiquants/virtualscroll`'s one signal that the host scrolls by keyboard itself (3.10.0, its README "Scrollbar
|
|
2952
2967
|
accessibility and the Tab order").
|
|
2953
2968
|
The bar carries `aria-hidden="true"`, so assistive technology sees no `scrollbar` and no `slider` in either view, named or not; its arrow buttons
|
|
2954
|
-
have `tabIndex=-1` and
|
|
2969
|
+
have `tabIndex=-1` and its `role="scrollbar"` element no `tabindex`, so the bar adds no Tab stop; and a press anywhere on the bar has its default prevented,
|
|
2955
2970
|
so it moves no focus, neither onto a part of the bar nor away from the composite. Every pointer interaction still scrolls: the arrows on a press and
|
|
2956
2971
|
while held, the track, the thumb and the tap-scroll circle.
|
|
2957
|
-
The bar
|
|
2972
|
+
The bar's `role="scrollbar"` element still carries its name (the engine key `verticalScrollBar`, below), which the hidden bar does not
|
|
2958
2973
|
expose.
|
|
2959
2974
|
- **Leaving the list** (`Ctrl+Home` / `Ctrl+End`, as in the WAI-ARIA feed pattern): focus moves to the last Tab stop before the list or the first one
|
|
2960
2975
|
after it — where real `Shift+Tab` from the list's first stop and real `Tab` from its last stop go — and the browser scrolls it into view as it does
|
|
@@ -3333,8 +3348,9 @@ the resize handle and the side pane lie outside the list.
|
|
|
3333
3348
|
The comment field is named by that heading (`aria-labelledby`; `labels.comments`), which renders whenever the form does, so the field has a name of
|
|
3334
3349
|
its own in the DetailList row, the side pane and the mobile overlay; its placeholder (`labels.commentPlaceholder`) stays a hint, not its name.
|
|
3335
3350
|
While a post is sent, the field keeps the draft, read-only, with the submit button disabled, and empties only when the post is accepted; a refused
|
|
3336
|
-
post (401, 403, a 5xx)
|
|
3337
|
-
|
|
3351
|
+
post (401, 403, a 5xx), and a post while the package is paused at a session end (never sent), leave the draft, its text and its caret untouched, so a
|
|
3352
|
+
viewer whose session ended sends it again after signing in again, on the same page (WCAG 2.2.5, with the host's re-authentication; see
|
|
3353
|
+
[Client wiring](#client-wiring)).
|
|
3338
3354
|
A report of a source that takes no comments and has none shows no empty section, and deleting the last comment of such a report removes the section,
|
|
3339
3355
|
so focus goes to the report's anchor above.
|
|
3340
3356
|
- **Mobile detail overlay** (List, single-column layout): the platform's modal dialog, a `<dialog data-daily-report-mobile-overlay>` (implicit
|
|
@@ -3776,12 +3792,10 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3776
3792
|
The centres of their 24 px circles are 12 px apart (the handle's on the panel boundary, the bar's 12 px before it), so the circles intersect and the
|
|
3777
3793
|
spacing exception does not apply either. Both keep the specified frame — the 2G channel and the 8 px scroll bar of both views — and no wider
|
|
3778
3794
|
construction has been decided yet.
|
|
3779
|
-
The splitter
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
optional `activationSizes` prop that a click under the drag threshold steps through, to which the List will pass its panel's minimum, default and
|
|
3784
|
-
maximum widths, 160, 360 and 520 px); until it ships, a pointer user who cannot drag keeps the List panel's width.
|
|
3795
|
+
The splitter meets WCAG 2.5.7 (Dragging Movements, AA): besides dragging and the arrow keys, a click or a tap on the handle that stays under
|
|
3796
|
+
`@aiquants/resize-panels`' drag threshold steps the List panel to its next preset width — the panel's minimum, default and maximum widths, 160, 360
|
|
3797
|
+
and 520 px, in that order and back to the first after the last (the handle's `activationSizes`; the stops are clipped to what the pair of panels can
|
|
3798
|
+
reach, and a stop where the border already is gets skipped). The handle's tooltip (`resizeHandleHint`) names all three ways.
|
|
3785
3799
|
The side-pane panel is at least 200 px wide: the frame around its centred selection prompt — 2G = 16 (the pane sits G inside its panel), the card
|
|
3786
3800
|
surface's insets 2 × 16 and the placeholder panel's insets 2 × 12, 72 in all — plus the prompt's longest phrase at the default 16 px root,
|
|
3787
3801
|
「選択してください。」 (9 full-width glyphs of `text-sm`, 9 × 0.875 rem = 126 px), is 198, rounded up to the 4 px lattice.
|
|
@@ -3858,12 +3872,13 @@ luminance by 0.026 in the light theme, and a `shadow-md` brings the ring down to
|
|
|
3858
3872
|
and the report headings tell where the viewer is), 2.4.9 (links name their purpose), 2.4.10 (sections carry headings), 2.4.12 and 2.4.13 (the focus
|
|
3859
3873
|
is never obscured, and its outline is 2 px at 3:1), 3.1.3, 3.1.4 (abbreviated source badges, **External Source Badge Configuration**), 3.2.5 and
|
|
3860
3874
|
3.3.6. Not met, by decision: 2.2.4 (Interruptions): live updates (SSE) apply as they arrive, with no pause, and
|
|
3861
|
-
the scroll anchoring keeps the rows on screen in place. Not met at AA: 2.5.8 for the List's resize handle and the scroll bar beside it
|
|
3862
|
-
the List's splitter (**Side pane** above): a path without dragging belongs to `@aiquants/resize-panels`, and larger hit areas for the handle and the
|
|
3875
|
+
the scroll anchoring keeps the rows on screen in place. Not met at AA: 2.5.8 for the List's resize handle and the scroll bar beside it (**Side pane** above): larger hit areas for the handle and the
|
|
3863
3876
|
bar wait for the same layout pass as 2.5.5. Not claimed yet: 2.5.5 (44 px targets), 1.4.8 (a line measure and the List preview's
|
|
3864
3877
|
leading) and 3.3.5 (a help control for the search syntax), which need a layout pass, and 3.1.6 (readings of names), which needs readings from the
|
|
3865
|
-
host's directory. 2.2.5 is met
|
|
3866
|
-
|
|
3878
|
+
host's directory. 2.2.5 (Re-authenticating) is met with the host: at a session end the package pauses without reloading and keeps every draft, the
|
|
3879
|
+
open edit form, the selection, the search and the scroll in memory; the host lets the viewer sign in again without leaving the page and advances
|
|
3880
|
+
`sessionEpoch`, and the package resumes and sends nothing again by itself ([Client wiring](#client-wiring)). 2.2.6 (Timeouts) is the host's: the
|
|
3881
|
+
package keeps unsent work only in the open tab's memory until it is closed, and the host states how long a session lasts and what ends it. The floating tap-scroll circle hides while the view root carries `data-daily-report-keyboard-focus` (through the class both views pass in
|
|
3867
3882
|
`VirtualScroll`'s tap-scroll circle options).
|
|
3868
3883
|
- **Action buttons and icons**: the List card's star and read toggles, the star, read, edit and delete buttons of the DetailList header and the side
|
|
3869
3884
|
pane, and the trash button of the viewer's comments share one 24 px round target that never shrinks, with a 16 px SVG icon centred in it (4 px on
|
|
@@ -4215,14 +4230,14 @@ locale**: English (`"en"`, the default) and Japanese (`"ja"`). Pick the language
|
|
|
4215
4230
|
/>
|
|
4216
4231
|
```
|
|
4217
4232
|
|
|
4218
|
-
- **One surface for all wording.** The catalog covers the
|
|
4233
|
+
- **One surface for all wording.** The catalog covers the engine chrome keys of `@aiquants/virtualscroll` (every label key it exports) plus 116 own keys: field headings, the
|
|
4219
4234
|
page title (`title`, passed to `renderHeader` and used as the accessible name of both lists), the lists' keyboard help, the row states (read, read and updated since, and
|
|
4220
4235
|
starred, editing), the updated-since-read pill and the List card's position read to screen readers, tabs, buttons, placeholders, the `confirm()` text, stream badges, the search box, its filter row and the
|
|
4221
4236
|
search's match indicator, the status screen and the page's status region and the mutation-failure message with its repeat count. The engine part of
|
|
4222
|
-
each catalog is `@aiquants/virtualscroll`'s own catalog of the same locale, reused by value, so the scroll arrows, the
|
|
4223
|
-
|
|
4237
|
+
each catalog is `@aiquants/virtualscroll`'s own catalog of the same locale, reused by value, so the scroll arrows, the name of the scroll bar and
|
|
4238
|
+
the "No items" text always speak the same language as the rest.
|
|
4224
4239
|
- **Forwarded to every embedded `VirtualScroll`.** Both the List and the DetailList pass `locale`
|
|
4225
|
-
and the
|
|
4240
|
+
and the engine keys of the resolved labels to their `VirtualScroll`. The engine label object keeps
|
|
4226
4241
|
its identity while its values are unchanged, so rebuilding `config.labels` on every render does not
|
|
4227
4242
|
re-render the memoized list subtree.
|
|
4228
4243
|
- **Formatter keys.** Twenty-two keys take arguments and are functions: `totalCount(count)`,
|
|
@@ -4241,7 +4256,7 @@ locale**: English (`"en"`, the default) and Japanese (`"ja"`). Pick the language
|
|
|
4241
4256
|
locale built once (the row positions and counts re-render on every stream publish); a host override receives
|
|
4242
4257
|
the raw number and formats it itself.
|
|
4243
4258
|
- **Fail-fast**: an unsupported `locale` (`"EN"`, `"ja-JP"`, `"fr"`, `""`, `null`, ...) throws a
|
|
4244
|
-
`RangeError` at render. So do an unknown `labels` key (a key error that lists
|
|
4259
|
+
`RangeError` at render. So do an unknown `labels` key (a key error that lists every key of `DAILY_REPORT_LABEL_KEYS`), a string
|
|
4245
4260
|
key whose value is not a string with non-whitespace content, and a formatter key whose value is not a
|
|
4246
4261
|
function. An `undefined` value keeps the catalog value.
|
|
4247
4262
|
- **`config` has a closed key set**: `apiBasePath`, `ssePath`, `locale`, `labels`,
|
|
@@ -4274,13 +4289,16 @@ locale**: English (`"en"`, the default) and Japanese (`"ja"`). Pick the language
|
|
|
4274
4289
|
- **Not tied to `locale`**: `sourceTypeConfigs` (host data). Only the built-in default badge map used when `sourceTypeConfigs`
|
|
4275
4290
|
is omitted takes its `Internal` label from `labels.sourceInternal`.
|
|
4276
4291
|
- **Host notifications**: `config.onError` receives `DailyReportErrorInfo` with the stable
|
|
4277
|
-
`operation` key
|
|
4292
|
+
`operation` key (an operation, or `"liveUpdates"` when the server refused the viewer the live updates), the `reason` (`"refused"` for a 403 or the
|
|
4293
|
+
live updates' `forbidden` end, `"failed"` otherwise) and `message` = `labels.operationRefused(operation)`, `labels.liveUpdatesRefused` or
|
|
4294
|
+
`labels.operationFailed(operation)` in the chosen locale. A session end (401) is never reported here: the package pauses and calls
|
|
4295
|
+
`onSessionExpired` instead.
|
|
4278
4296
|
- **`locale` is the only language axis.** This package has no BCP 47 `formatLocale` option: digit
|
|
4279
4297
|
grouping follows `locale` (`en` → `"en-US"`, `ja` → `"ja-JP"`) and dates stay in ISO form. Packages
|
|
4280
4298
|
that do format dates (for example `@aiquants/period-slider`) name that separate axis `formatLocale`.
|
|
4281
4299
|
|
|
4282
|
-
Exported API (`@aiquants/daily-report/client`): `DAILY_REPORT_LABEL_KEYS` (
|
|
4283
|
-
first), `DAILY_REPORT_LABEL_CATALOGS` (the frozen catalogs), `resolveDailyReportLabels(locale, labels)`
|
|
4300
|
+
Exported API (`@aiquants/daily-report/client`): `DAILY_REPORT_LABEL_KEYS` (every key: the engine keys `@aiquants/virtualscroll` exports, in its order,
|
|
4301
|
+
first, then the 116 own keys), `DAILY_REPORT_LABEL_CATALOGS` (the frozen catalogs), `resolveDailyReportLabels(locale, labels)`
|
|
4284
4302
|
(the effective frozen labels — the catalog object itself when `labels` is `undefined`), the resolved
|
|
4285
4303
|
`locale` / `labels` on `useDailyReportConfig()`, and the types `DailyReportLocale` (= `VirtualScrollLocale`),
|
|
4286
4304
|
`DailyReportLabels`, `DailyReportLabelOverrides` and `DailyReportOperation`.
|
|
@@ -4293,8 +4311,6 @@ first), `DAILY_REPORT_LABEL_CATALOGS` (the frozen catalogs), `resolveDailyReport
|
|
|
4293
4311
|
| `scrollRight` | engine: horizontal arrow (not rendered by this package) | Scroll right | 右へスクロール |
|
|
4294
4312
|
| `verticalScrollBar` | engine: name (`aria-label`) of the vertical ScrollBar (`role="scrollbar"`); both views hide their pointer-only bar from assistive technology, so it is not announced | Vertical | 縦方向 |
|
|
4295
4313
|
| `horizontalScrollBar` | engine: name of the horizontal ScrollBar (not rendered by this package) | Horizontal | 横方向 |
|
|
4296
|
-
| `verticalScrollThumb` | engine: name (`aria-label`) of the vertical ScrollBar's thumb (`role="slider"`), inside the hidden bar | Vertical scroll position | 縦スクロール位置 |
|
|
4297
|
-
| `horizontalScrollThumb` | engine: name of the horizontal ScrollBar's thumb (not rendered by this package) | Horizontal scroll position | 横スクロール位置 |
|
|
4298
4314
|
| `scrollToTop` | engine: top pill (not enabled by this package) | Top | 先頭へ |
|
|
4299
4315
|
| `scrollToBottom` | engine: bottom pill (not enabled by this package) | Bottom | 末尾へ |
|
|
4300
4316
|
| `noItems` | engine: the one message of an empty List or DetailList, over the top of the list | No items | 項目がありません |
|
|
@@ -4358,6 +4374,7 @@ first), `DAILY_REPORT_LABEL_CATALOGS` (the frozen catalogs), `resolveDailyReport
|
|
|
4358
4374
|
| `deleteReport` | report delete button | Delete | 削除する |
|
|
4359
4375
|
| `edit` | edit button of the viewer's own report (`aria-label` / tooltip) | Edit | 編集 |
|
|
4360
4376
|
| `resizeHandle` | list / detail resize handle `aria-label` | Resize the border between the report list and the detail pane | 日報一覧と詳細ペインの境界のサイズ変更ハンドル |
|
|
4377
|
+
| `resizeHandleHint` | list / detail resize handle tooltip (`title`): the ways to move the border | Drag or use the arrow keys to resize, or click to step through the preset widths | ドラッグか矢印キーで幅を変え、クリックで決まった幅を順に切り替える |
|
|
4361
4378
|
| `close` | mobile overlay close button, the error notice's close `aria-label` | Close | 閉じる |
|
|
4362
4379
|
| `formTitle` | edit form | Title | タイトル |
|
|
4363
4380
|
| `formTitlePlaceholder` | edit form | Enter the report title | 日報のタイトルを入力 |
|
package/dist/client.d.mts
CHANGED
|
@@ -37,7 +37,7 @@ type DailyReportDetailListProps = {
|
|
|
37
37
|
scrollRestoreRef?: RefObject<DailyReportDetailListScrollRestore>;
|
|
38
38
|
};
|
|
39
39
|
declare const DailyReportDetailList: (props: DailyReportDetailListProps) => react.JSX.Element;
|
|
40
|
-
type DailyReportSearchFailure = "invalid" | "busy" | "unavailable" | "failed";
|
|
40
|
+
type DailyReportSearchFailure = "invalid" | "busy" | "unavailable" | "failed" | "refused";
|
|
41
41
|
type DailyReportLocale = VirtualScrollLocale;
|
|
42
42
|
type DailyReportOperation = Exclude<DailyReportActionIntent, "clearCache">;
|
|
43
43
|
type DailyReportLabels = VirtualScrollLabels & {
|
|
@@ -84,6 +84,7 @@ type DailyReportLabels = VirtualScrollLabels & {
|
|
|
84
84
|
readonly reload: string;
|
|
85
85
|
readonly loadingIds: string;
|
|
86
86
|
readonly streamFailed: string;
|
|
87
|
+
readonly liveUpdatesRefused: string;
|
|
87
88
|
readonly streamRetry: string;
|
|
88
89
|
readonly streamRevalidating: string;
|
|
89
90
|
readonly selectPrompt: string;
|
|
@@ -101,6 +102,7 @@ type DailyReportLabels = VirtualScrollLabels & {
|
|
|
101
102
|
readonly deleteReport: string;
|
|
102
103
|
readonly edit: string;
|
|
103
104
|
readonly resizeHandle: string;
|
|
105
|
+
readonly resizeHandleHint: string;
|
|
104
106
|
readonly close: string;
|
|
105
107
|
readonly formTitle: string;
|
|
106
108
|
readonly formTitlePlaceholder: string;
|
|
@@ -141,6 +143,7 @@ type DailyReportLabels = VirtualScrollLabels & {
|
|
|
141
143
|
readonly reportSummaryLoadFailed: (reportHubId: number) => string;
|
|
142
144
|
readonly interviewerWithAffiliation: (name: string, affiliation: string) => string;
|
|
143
145
|
readonly operationFailed: (operation: DailyReportOperation) => string;
|
|
146
|
+
readonly operationRefused: (operation: DailyReportOperation) => string;
|
|
144
147
|
readonly noticeRepeated: (count: number) => string;
|
|
145
148
|
readonly rowState: (state: {
|
|
146
149
|
readonly readState: DailyReportReadState;
|
|
@@ -170,8 +173,6 @@ declare const DAILY_REPORT_LABEL_KEYS: readonly [
|
|
|
170
173
|
"scrollRight",
|
|
171
174
|
"verticalScrollBar",
|
|
172
175
|
"horizontalScrollBar",
|
|
173
|
-
"verticalScrollThumb",
|
|
174
|
-
"horizontalScrollThumb",
|
|
175
176
|
"scrollToTop",
|
|
176
177
|
"scrollToBottom",
|
|
177
178
|
"noItems",
|
|
@@ -218,6 +219,7 @@ declare const DAILY_REPORT_LABEL_KEYS: readonly [
|
|
|
218
219
|
"reload",
|
|
219
220
|
"loadingIds",
|
|
220
221
|
"streamFailed",
|
|
222
|
+
"liveUpdatesRefused",
|
|
221
223
|
"streamRetry",
|
|
222
224
|
"streamRevalidating",
|
|
223
225
|
"selectPrompt",
|
|
@@ -235,6 +237,7 @@ declare const DAILY_REPORT_LABEL_KEYS: readonly [
|
|
|
235
237
|
"deleteReport",
|
|
236
238
|
"edit",
|
|
237
239
|
"resizeHandle",
|
|
240
|
+
"resizeHandleHint",
|
|
238
241
|
"close",
|
|
239
242
|
"formTitle",
|
|
240
243
|
"formTitlePlaceholder",
|
|
@@ -275,6 +278,7 @@ declare const DAILY_REPORT_LABEL_KEYS: readonly [
|
|
|
275
278
|
"reportSummaryLoadFailed",
|
|
276
279
|
"interviewerWithAffiliation",
|
|
277
280
|
"operationFailed",
|
|
281
|
+
"operationRefused",
|
|
278
282
|
"noticeRepeated",
|
|
279
283
|
"rowState",
|
|
280
284
|
"rowEditingState",
|
|
@@ -364,7 +368,8 @@ type DailyReportHeaderProps = {
|
|
|
364
368
|
annotation?: ReactNode;
|
|
365
369
|
};
|
|
366
370
|
type DailyReportErrorInfo = {
|
|
367
|
-
operation: DailyReportOperation;
|
|
371
|
+
operation: DailyReportOperation | "liveUpdates";
|
|
372
|
+
reason: "failed" | "refused";
|
|
368
373
|
message: string;
|
|
369
374
|
cause?: unknown;
|
|
370
375
|
};
|
|
@@ -413,6 +418,7 @@ type DailyReportPageProps = {
|
|
|
413
418
|
user?: DailyReportUser;
|
|
414
419
|
userId?: string | null;
|
|
415
420
|
config: DailyReportClientConfigInput;
|
|
421
|
+
sessionEpoch: number;
|
|
416
422
|
};
|
|
417
423
|
declare const DailyReportPage: ({ config, ...rest }: DailyReportPageProps) => react.JSX.Element;
|
|
418
424
|
type DailyReportResolvedContentProps = {
|
|
@@ -427,8 +433,10 @@ type UseDailyReportSseConnectionOptions = {
|
|
|
427
433
|
onMessage: (payload: Exclude<DailyReportSseMessage, {
|
|
428
434
|
type: "connected";
|
|
429
435
|
}>) => void;
|
|
436
|
+
onSessionEnded: () => void;
|
|
437
|
+
onRefused: () => void;
|
|
430
438
|
};
|
|
431
|
-
declare const useDailyReportSseConnection: ({ isSseEnabled, onMessage }: UseDailyReportSseConnectionOptions) => DailyReportSseConnectionStatus;
|
|
439
|
+
declare const useDailyReportSseConnection: ({ isSseEnabled, onMessage, onSessionEnded, onRefused }: UseDailyReportSseConnectionOptions) => DailyReportSseConnectionStatus;
|
|
432
440
|
type ReportBusinessDate = DailyReportDetail["date"];
|
|
433
441
|
type DailyReportActionFunctions = {
|
|
434
442
|
toggleSse: () => void;
|
package/dist/client.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ type DailyReportDetailListProps = {
|
|
|
37
37
|
scrollRestoreRef?: RefObject<DailyReportDetailListScrollRestore>;
|
|
38
38
|
};
|
|
39
39
|
declare const DailyReportDetailList: (props: DailyReportDetailListProps) => react.JSX.Element;
|
|
40
|
-
type DailyReportSearchFailure = "invalid" | "busy" | "unavailable" | "failed";
|
|
40
|
+
type DailyReportSearchFailure = "invalid" | "busy" | "unavailable" | "failed" | "refused";
|
|
41
41
|
type DailyReportLocale = VirtualScrollLocale;
|
|
42
42
|
type DailyReportOperation = Exclude<DailyReportActionIntent, "clearCache">;
|
|
43
43
|
type DailyReportLabels = VirtualScrollLabels & {
|
|
@@ -84,6 +84,7 @@ type DailyReportLabels = VirtualScrollLabels & {
|
|
|
84
84
|
readonly reload: string;
|
|
85
85
|
readonly loadingIds: string;
|
|
86
86
|
readonly streamFailed: string;
|
|
87
|
+
readonly liveUpdatesRefused: string;
|
|
87
88
|
readonly streamRetry: string;
|
|
88
89
|
readonly streamRevalidating: string;
|
|
89
90
|
readonly selectPrompt: string;
|
|
@@ -101,6 +102,7 @@ type DailyReportLabels = VirtualScrollLabels & {
|
|
|
101
102
|
readonly deleteReport: string;
|
|
102
103
|
readonly edit: string;
|
|
103
104
|
readonly resizeHandle: string;
|
|
105
|
+
readonly resizeHandleHint: string;
|
|
104
106
|
readonly close: string;
|
|
105
107
|
readonly formTitle: string;
|
|
106
108
|
readonly formTitlePlaceholder: string;
|
|
@@ -141,6 +143,7 @@ type DailyReportLabels = VirtualScrollLabels & {
|
|
|
141
143
|
readonly reportSummaryLoadFailed: (reportHubId: number) => string;
|
|
142
144
|
readonly interviewerWithAffiliation: (name: string, affiliation: string) => string;
|
|
143
145
|
readonly operationFailed: (operation: DailyReportOperation) => string;
|
|
146
|
+
readonly operationRefused: (operation: DailyReportOperation) => string;
|
|
144
147
|
readonly noticeRepeated: (count: number) => string;
|
|
145
148
|
readonly rowState: (state: {
|
|
146
149
|
readonly readState: DailyReportReadState;
|
|
@@ -170,8 +173,6 @@ declare const DAILY_REPORT_LABEL_KEYS: readonly [
|
|
|
170
173
|
"scrollRight",
|
|
171
174
|
"verticalScrollBar",
|
|
172
175
|
"horizontalScrollBar",
|
|
173
|
-
"verticalScrollThumb",
|
|
174
|
-
"horizontalScrollThumb",
|
|
175
176
|
"scrollToTop",
|
|
176
177
|
"scrollToBottom",
|
|
177
178
|
"noItems",
|
|
@@ -218,6 +219,7 @@ declare const DAILY_REPORT_LABEL_KEYS: readonly [
|
|
|
218
219
|
"reload",
|
|
219
220
|
"loadingIds",
|
|
220
221
|
"streamFailed",
|
|
222
|
+
"liveUpdatesRefused",
|
|
221
223
|
"streamRetry",
|
|
222
224
|
"streamRevalidating",
|
|
223
225
|
"selectPrompt",
|
|
@@ -235,6 +237,7 @@ declare const DAILY_REPORT_LABEL_KEYS: readonly [
|
|
|
235
237
|
"deleteReport",
|
|
236
238
|
"edit",
|
|
237
239
|
"resizeHandle",
|
|
240
|
+
"resizeHandleHint",
|
|
238
241
|
"close",
|
|
239
242
|
"formTitle",
|
|
240
243
|
"formTitlePlaceholder",
|
|
@@ -275,6 +278,7 @@ declare const DAILY_REPORT_LABEL_KEYS: readonly [
|
|
|
275
278
|
"reportSummaryLoadFailed",
|
|
276
279
|
"interviewerWithAffiliation",
|
|
277
280
|
"operationFailed",
|
|
281
|
+
"operationRefused",
|
|
278
282
|
"noticeRepeated",
|
|
279
283
|
"rowState",
|
|
280
284
|
"rowEditingState",
|
|
@@ -364,7 +368,8 @@ type DailyReportHeaderProps = {
|
|
|
364
368
|
annotation?: ReactNode;
|
|
365
369
|
};
|
|
366
370
|
type DailyReportErrorInfo = {
|
|
367
|
-
operation: DailyReportOperation;
|
|
371
|
+
operation: DailyReportOperation | "liveUpdates";
|
|
372
|
+
reason: "failed" | "refused";
|
|
368
373
|
message: string;
|
|
369
374
|
cause?: unknown;
|
|
370
375
|
};
|
|
@@ -413,6 +418,7 @@ type DailyReportPageProps = {
|
|
|
413
418
|
user?: DailyReportUser;
|
|
414
419
|
userId?: string | null;
|
|
415
420
|
config: DailyReportClientConfigInput;
|
|
421
|
+
sessionEpoch: number;
|
|
416
422
|
};
|
|
417
423
|
declare const DailyReportPage: ({ config, ...rest }: DailyReportPageProps) => react.JSX.Element;
|
|
418
424
|
type DailyReportResolvedContentProps = {
|
|
@@ -427,8 +433,10 @@ type UseDailyReportSseConnectionOptions = {
|
|
|
427
433
|
onMessage: (payload: Exclude<DailyReportSseMessage, {
|
|
428
434
|
type: "connected";
|
|
429
435
|
}>) => void;
|
|
436
|
+
onSessionEnded: () => void;
|
|
437
|
+
onRefused: () => void;
|
|
430
438
|
};
|
|
431
|
-
declare const useDailyReportSseConnection: ({ isSseEnabled, onMessage }: UseDailyReportSseConnectionOptions) => DailyReportSseConnectionStatus;
|
|
439
|
+
declare const useDailyReportSseConnection: ({ isSseEnabled, onMessage, onSessionEnded, onRefused }: UseDailyReportSseConnectionOptions) => DailyReportSseConnectionStatus;
|
|
432
440
|
type ReportBusinessDate = DailyReportDetail["date"];
|
|
433
441
|
type DailyReportActionFunctions = {
|
|
434
442
|
toggleSse: () => void;
|