Repository navigation
fix(app-shell): a failed comments or activity read on a record page shows a load-failure notice with a Retry, not the empty state - #29358
Merged
Conversation
…hows a load-failure notice with a Retry, not the empty state A 5xx or a request that never got an answer used to settle the discussion panel on its empty state and the timeline tab's badge on 0. The feed reads now record answered | refused | failed per source; a failed one draws a notice with a Retry that re-reads only the failed sources, directly. Refusals, empty answers and 404s keep today's handling. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jT854xvoBjntpsRE1F
…essage names A rejection with no status now reads as a network failure and shows the load-failure notice, so the rows that meant a 403 or a 404 carry it, as the ObjectStack client does. A refused comment read settles on its no-permission line. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jT854xvoBjntpsRE1F
ar, de, es, fr, ja, ko, pt and ru carry activityLoadFailed, commentsLoadFailed and retryLoadFeed at the en place, worded as each pack's attachmentsLoadFailed and retryLoadAttachments already are. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jT854xvoBjntpsRE1F
Contributor
Author
|
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu 席位核对 · ACCEPT · 2026-11-02T13:33ZHead-sha:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Requested by Steedos · project thread
Fixes #29188
Clause-②: yes (widening)
Metadata-protocol: none
维护者速读
@object-ui/react的DiscussionContextValue和时间线组件新增三个可选成员,均为加宽。附件面板 main 上已经能显示失败与重试,本 PR 只加了测试。回滚即 revert 本 PR。ui/packages/app-shell/src/views/RecordDetailView.tsx的feedReadVerdictOf与handleRetryFeed,以及 feed effect 里的retrying分支;②ui/packages/plugin-detail/src/RecordActivityTimeline.tsx的failedNotice;③ui/packages/plugin-detail/src/renderers/record-activity.tsx的计数置空。pnpm --dir ui exec vitest run packages/app-shell/src/views/RecordDetailView.feedLoadFailure-29188.test.tsx,预期 10 个测试全绿,覆盖评论 500、活动 500、重试、空结果对照、拒绝对照和附件 500。What changes
A record page's comments read and activity read each end in one of three verdicts per source:
answered,refusedorfailed. Before this change a read could only be refused or not, so a 5xx fell through to the empty state.failedis a 5xx, or a rejection with no status at all (the request never got an answer):classifyLoadError'snetwork, minus the 4xx statuses it also folds there (feedReadVerdictOfinRecordDetailView.tsx). A 404 (a table the deployment does not serve), an object that withholds its API (api-disabled) and a 400 (rejected) stayanswered, as before.refusedis unchanged (isRefusedFeedRead, objectui#11195).RecordActivityTimelinedraws "We couldn't load the comments for this record." / "…the activity…" (zh: 无法加载此记录的评论。/ 活动。) with a Retry button, in place of the empty state when no rows came back and above the rows when some did. This applies to the panel, the 动态 tab (stream) and the 动态 panel (peek). Only the i18n sentence is rendered: no status code, no server text. The header count, the collapsed chatter label and the 动态 count (record:activity's reported count andRecordTimelineCountProbe) are unknown (no number) while a read has failed, as for a refusal.handleRetryFeed) re-reads only the failed sources, directly throughdataSource.find, never the page payload (which already answered). It does not touch the stream count the payload gave. The button is disabled while the re-read is in flight over rows on screen, and a retry that fails again keeps the notice.DiscussionContextValue(@object-ui/react) gains the optionalactivityFailed,commentsFailedandonRetryFeed.record:activityandrecord:chatterforward them, andRecordChatterPanelandRecordActivityTimelinetake them as optional props. A host that sets none of them renders exactly as before.detail.activityLoadFailed,detail.commentsLoadFailedanddetail.retryLoadFeedin all ten packs (en, zh, ar, de, es, fr, ja, ko, pt, ru) at the en place, worded as each pack'sattachmentsLoadFailed/retryLoadAttachments, plus the provider-less defaults inuseDetailTranslation.ts. The eight non-en/zh packs came in claim amendment 2, afterall-locales-key-parity.test.tswent red on Test UI 14/16 at 89ec072.RecordAttachmentsPanel's "We couldn't load the attachments for this record." with a Retry, and the count store holds no value, so no badge is drawn. The payload path is now pinned.Contract review
Seat self-review, per the 10:43Z triage ruling. Every addition is optional and additive; no member is removed, renamed or narrowed.
DiscussionContextValue(@object-ui/react)activityFailed?: boolean,commentsFailed?: boolean,onRetryFeed?: () => voidRecordActivityTimelineProps(@object-ui/plugin-detail)false,false, no Retry buttonRecordChatterPanelProps(@object-ui/plugin-detail)detaillocale namespace (@object-ui/i18n)activityLoadFailed,commentsLoadFailed,retryLoadFeed, in all ten packsNo spec, metadata or wire shape changes; the server's page payload is read as before.
Pins changed
RecordDetailView.feedRefusal-11195.test.tsx, "a 500 is not "no permission"": an activity 500 now shows the load-failure notice instead of the empty state. It still asserts the no-permission line is absent.RecordDetailView.feedLoading.test.tsx(claim amendment 1, test only): its rejections were barenew Error('403 FEEDS_DISABLED')/new Error('404 sys_activity')with no status. A statusless rejection is what a network failure looks like, so three rows went red. Each rejection now carries the status its message names, in the ObjectStack client's shape (httpStatus,code), as the 11195 test already does.Tests
RecordDetailView.feedLoadFailure-29188.test.tsx(10 tests). It uses the realObjectStackAdapterover a held transport, theRecordDetailView.recordOpenOneRequest-28470rig, under StrictMode. It covers a comments 500 as a payload part and as a direct GET (notice, Retry, no empty copy, no leak, 动态 tab with no count), Retry re-reading onlysys_commentdirectly (no activity re-read, the notice gone once it answers), a retry that fails again, an activity 500 both ways, the empty-200 controls both ways, the 403 refusal control (no-permission line, no Retry) and the attachments payload 500 pin.RecordActivityTimeline.loadFailed-29188.test.tsx(9 tests), through the real en and zh packs and therecord:chatterblock under a hostDiscussionContext, plus thepeekface. It covers the notice in place of "No comments yet" (zh: 无法加载此记录的评论。, never 暂无评论), Retry calling the host, rows kept with the notice above them, the activity line, no Retry when the host offers none, a refusal and a failure side by side, the empty control, and the disabled Retry while loading.Activity0tab badge; attachments 500 → the panel's unavailable state with Retry and no count.scripts/ablation-replace.mjs,feedReadVerdictOfforced back toansweredfor a 5xx): 7 of 17 red across the new page test and the 11195 file. Those are the six failure rows and the flipped 11195 row; the controls, the refusal row and the attachments pin stayed green. Restored: blob equals HEAD,git diff HEADempty.ui/underscripts/pm/os-verify-lock.sh,--maxWorkers=2, at merged head 89ec072: the 109 test files that name the timeline, the chatter panel,DiscussionContext, the feed renderers or the refusal flags, plus theRecordDetailViewtests that readsys_comment/sys_activity/ the payload / the timeline, plus the two new files. 111 files, 2609 tests, exit 0.apps/console/src/__tests__/record-block-record-reach.test.tsx: 13 passed.pnpm exec eslinton the 13 changed files: 0 errors; the warnings are the files' existinganyand hook warnings.packages/i18n/suite 95 files, 1443 passed, 13 skipped, exit 0;all-locales-key-parity.test.tswith the timeline test: 54 passed.Acceptance notes
RecordDetailView.feedLoading.test.tsx, test only) and amendment 2 (the eight other locale packs). The diff stays inside them.classifyLoadError'snetworkkind and then excludes the 4xx statuses that kind also holds, so a status-carrying 404 keeps the empty state the feedLoading pins describe. This matches the claim's "5xx or network" reading.api-disabled) or answers 400 still shows the empty state, as the claim keeps. Neither is retryable, so a Retry would be wrong advice there.Verification
node scripts/pm/dispatch-gates.mjs --ranat 53d0b77 (re-run after the locale commit; the derived list is unchanged): 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN; every recorded exit is 0.pnpm --dir ui exec vitest run scripts/at 53d0b77: 169 files passed, 2 skipped (4903 tests).node ui/scripts/check-new-cross-file-line-citations.mjs: 0 new citations.pnpm exec turbo run type-check --filter=@object-ui/app-shell --filter=@object-ui/react --filter=@object-ui/i18n --filter=@object-ui/plugin-detail --concurrency=2at 89ec072: exit 0, 68 of 68 tasks.node scripts/check-sdui-manifest.mjs: exit 0.node scripts/check-changeset-no-major.mjs --base origin/main,node scripts/check-adr-0087-registration.mjs --base origin/main,node scripts/check-closing-keyword-parity.mjsandnode scripts/check-partof-closing-keyword.mjs, with this body as the event: exit 0 each.Human Minimum
packages/specholds no runtime logic. (not touched)pnpm lintpasses. (CI runs the repo lint)main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed. (not touched)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_01QsR2jT854xvoBjntpsRE1F