fix(opportunity-page): keep the deal's empty classification, campaign and notes sections on screen - #1991
Merged
objectstack-fleet[bot] merged 3 commits intoOct 3, 2026
Conversation
… and notes sections on screen An all-empty `record:details` section renders nothing by the platform default (objectui#8603 ruling A), so on a deal carrying only its required fields the Details tab dropped the deal's type and source, its campaign, and its description and next step. `hideEmpty: false` on those three group references keeps them as labelled empty rows to fill in. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ER8ntXZhYebyQ66aXWdjfT
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ER8ntXZhYebyQ66aXWdjfT
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
…pty-group fix makes false The opportunity Campaigns section now renders while empty, so the unreleased 806 note that it appears only once a campaign is set no longer holds. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ER8ntXZhYebyQ66aXWdjfT
This was referenced Oct 3, 2026
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.
Fixes #1211
Clause-②: no
What changes
src/sales/pages/opportunity_detail.page.ts: three of the seven{ group }sections on the Details tab now carryhideEmpty: false. They areclassification,campaignandnotes. Nothing else in the page changes, and nofieldGroupschange.The platform default is objectui#8603 ruling A: a section whose fields are all empty renders nothing, with no heading and no skeleton. On a deal that carries only its required fields, that default removed the deal's type and source, its campaign, and its description and next step from the page. These are the fields the confirmed plan (
5823958911, maintainer: 「同意。」) asked to keep visible. WithhideEmpty: falsethey show as labelled empty rows that a seller can fill in.Mapping: old hand-written sections to today's groups (read from
crm_opportunity.fieldGroupsmembership)infonamebasicinfocrm_accountbasicinfoowner_idbasicinfotypeclassificationinfolead_sourceclassificationinfocrm_campaigncampaigndescriptiondescriptionnotesdescriptionnext_stepnotesSo the
infoanddescriptionsections of the plan land onclassification,campaignandnotes. The share ofinfothat sits inbasicis already on screen for every deal, in the title and the strip.basicitself is left alone; see the measurement below.Before / after: sparse deal, measured in Chromium on 17.6.0
Setup: a fresh
objectstack dev -p 4811 --no-watch --compileboot. The sparse deal was created byPOST /api/v1/data/crm_opportunityas admin with required fields only:name,crm_account,amount,stage = prospectingandclose_date. It has no type, lead source, campaign, description, next step or primary contact. Before each probe, the servedGET /api/v1/meta/page/opportunity_detail_pagesections were compared with the compiled artifact and with the source, and they were equal.1e47470e)4f3a58c4)+ basic, + financialsbasicprimary_contactfinancialsamountandexpected_revenueare in the strip)classificationtype,lead_source,win_reason,loss_reason,loss_detailscampaign(collapsed)crm_campaignsales_processstage,stage_entry_date,approval_status,approved_datecrm_forecast(collapsed)days_in_stage,is_private,forecast_categorynotesdescription,next_stepReasons for each choice:
classification,campaign,notes: on. Together they hold every field of the oldinfoanddescriptionsections that is not already in the title or the strip. Each went from absent to present.financials: off. This is the PM'shideEmpty: falsethe section still renders nothing: no heading and no empty shell. The renderer first removes the strip's fields from the group's members, which leaves an empty list. It then returnsnullfor an empty list whateverhideEmptysays. On this page the key would be authored and do nothing, so it is not authored.basic: off. With the key it renders a "Basic Information" card holding a single empty Primary Contact row.primary_contactwas never part of the oldinfosection, and the plan's list (source, campaign, type, next step, description) does not name it. The rest ofbasicis shown on every deal in the title and the strip.The "probe only" column comes from a one-off mutation run through
node scripts/ablation-replace.mjsfrom objectstack in WRAP mode. The anchor matched once, the blob changed from6d276c2a5d73tocc438f42b412, and the served sections showed the mutation. The restore was proven by blob equal to HEAD (6d276c2a5d73) and an emptygit diff HEAD. Nothing from that run is committed.A deal that already has values does not change. Measured after the change on seeded
JQBwoPdN8lNzs6q5: Classification shows Type and Lead Source, with Show 3 empty fields folding the rest as before. Campaigns now appears empty, as it does on 17 of the 23 seeded deals, which have no campaign. On seededgc1G4KqzWSOD-Ofo, Notes & Next Steps now appears with 2 empty rows. In the 17.6.0 console bundle (.objectui-sha31971ff1),DetailSectionreadshideEmptyin exactly one place: the branch where every field is empty. A section with any value is therefore not affected by the key.Legality of the key (hypothesis 1)
Confirmed, with one correction.
PageSchema.safeParseon the edited page succeeds, but it cannot tell a good edit from a bad one: it also accepts all three controls below, because componentpropertiesis an open record at thePageSchemalevel. The parse that can tell them apart isRecordDetailsProps(=== ComponentPropsMap['record:details'],@objectstack/spec@17.6.0):success: true, withhideEmpty: falsekept on the three sections.collapsible: truebesidegroup: refused (collapsiblecannot be combined withgroup).hideEmpty: 'no': refused (expected boolean).hideEmptyX: refused (unrecognized key).pnpm validatepasses. The author-time warnings stay at 7 → 7, and the two rule lists are identical.Verification
OS_VERIFY_LOCK_SLOT=hotcrm-issue-1211 bash scripts/pm/os-verify-lock.sh -c 'pnpm verify'atbfe9602a(the HEAD of this PR):os-verify-lock: VERDICT command-exit 0. Inside the chain:Validation passed·tsc --noEmitclean · lint1 warning(s), 16 suggestion(s)·0 i18n/missing-* issues·source hygiene clean·source token ratchet clean·Build complete(7 author-time warnings) ·Test Files 174 passed (174),Tests 3705 passed | 1 skipped.src/sales: interaction layer ~27,633 → ~27,646 (+13; chars 110,531 → 110,585). Authored total ~96,545 → ~96,558. The ceilings (31,000 / 100,000) are unchanged.test/detail-section-dedup.test.tsreads these sections, and it does not readhideEmpty. It stays green.Acceptance notes
contact_info,assignment,address,duplicatesandadditionalvanish.assignment(onlyowner_id, which is in the strip) is an empty list, sohideEmptycannot bring it back. On a fresh open case, 3 of 6 groups render.origin,slaandresolutionvanish. The earlier note that the case page is not at risk predates the group form and no longer holds..changeset/806-detail-sections-group-ref.md(still unreleased) says the Campaigns group appears once a campaign is set. After this PR it appears always. This PR's changeset states the new behaviour. The older sentence is outside this PR's file surface.--no-watchwithout--compile. It served the staledist/objectstack.json; the CLI printsthis boot serves the STALE buildfor this case. The served-metadata check caught it, and every "after" reading above comes from a--compileboot.Generated by Claude Code