fix(admin): keep the lookup's prefill through a repeat lookup and lay out the NSFW row by its column (SONA-220) - #440
Conversation
…, and pin the merged SONA-156 and SONA-220 rows (SONA-220) On the upload form a second artist lookup blanked the source post URL the first one had written before the new result was in, and the tag suggestion control answered that change by dropping its chips and rating. The fields now wait for the result: a lookup that lands on the same post leaves the URL untouched, a different post replaces it, and no post clears it. The panel's own state (applied artist, extra parents) still resets when the search starts. A parent change keeps the full reset. The lookup's rating pill wraps at every width on both forms, and shares the wrapped indent with the suggestion note in the NSFW row. Tests pin the joined aria-describedby on the source field, the three re-seed lines in the edit page's resetForImage, the parent-move reset, the clash sentence after a lookup-written URL, and both directions of the "set that lookup aside" line. The e2e watch-ignores test now knows the two SONA-220 persist roots.
…d fields, and key the NSFW row to its column (SONA-220) The edit page now keeps the lookup-written source post URL and commissioned date until the new result lands, the same way the upload form does, so a repeat lookup no longer drops the tag-suggestion chips. When a result empties a field the previous lookup filled, the panel's status line says so instead of claiming the field was left alone. The NSFW row on both forms is laid out by the width of the form's column, not the window: both forms are a container, the row stacks with the 24px indent below 560px of column, and above it the two rating pills take a zero flex basis with a 14ch floor so the button stays beside the checkbox while the pills wrap their text. The pill radius is a fixed 12px so a wrapped pill keeps its end caps clear of the text. Tests cover the edit page's same-post, different-post and no-post repeat lookups, the emptied-field status kinds, the date-clearing branch on the upload form, and the row at 320, 900 and 1280.
…he NSFW row's rules in one place (SONA-220) A second lookup that finds nothing now empties the URL and date the previous lookup filled, drops their tags, and says so in the panel's no-match state. The status sentences for an emptied field say "cleared", the same verb as the panel's announcement, and no longer claim the result had no post when the post exists but belongs to another piece; a clash that empties the URL gets its own sentence. The Japanese strings use 検索 like the rest of the file. The searching announcement names the new artist details it clears, and a parent change on the upload form announces which shared fields it emptied. The NSFW row's container queries and the rating pill's rule live once in app.css, the two ranges abut, the wide row uses a 4px gap so all four items fit the 600px column, and the narrow row stacks so the 24px indent only lands on an item on its own line. The page-scoped copies are gone.
…he emptied copy (SONA-220) When the parent tile changes and the new parent's result refills only one of the two shared fields, the panel now says the other was cleared and the live region announces it, instead of claiming it was left as it was. The Japanese clash sentence brackets the title like its siblings, the parent-change announcements say "parent image", and the date sentence on the no-match state blames the lookup rather than a result that does not exist. The panel derives its emptied-only state from the sentence it renders, the tile pill keeps overflow-wrap: anywhere inside its narrow tile, the button in the wide NSFW row sits 4px off the rating items, and the cleared sentence uses the foreground colour so it reads as a report rather than a hint.
…anel cannot report it (SONA-220) On the upload form a parent change used to speak its clearing per field and then have the refill announcement overwrite it in the same tick, so the operator never heard which field went blank. The move now returns what it wrote and what it cleared, applyShared is the single writer of the cleared record, and each caller says exactly one sentence: the return to a new set borrows the panel's own filled-and-cleared line for the mixed case, and the plain parent change stays silent unless the new parent has no lookup to report through. The panel's failed state shows the cleared sentence above the retry advice, and every sentence that reports a field going blank uses the foreground colour. The date sentence gains its next step in both languages, and the markup tests pin the single writer and the single announcement rather than the literal shape of the code.
… panel and the announcer (SONA-220) The panel and the upload form's live region now read the same function to turn a status kind into a sentence, so a parent move can never announce a reason the panel contradicts. A dated clash over a URL the last lookup filled gets its own sentence that names both halves, a move onto a tile whose lookup is still running keeps what it emptied until that result lands, and a thrown result resets the record. Three status sentences gain their next step, the cleared sentence on the failed state sits clear of the failure lead, and the announcement chain is one helper used by both callers. Tests cover the spoken sentence for a move onto a tile with no lookup, one mid-search, one that then fails, removing the parent tile itself, and the emptied styling on both clash sentences.
…n in-flight lookup (SONA-220) When a parent move lands on a tile whose lookup is still running, the record of what the move emptied now drops any field the operator types into before the result arrives, and cancelling that lookup drops the record entirely. The new clash sentence names the post Sona just found rather than a pronoun that pointed at the wrong noun, the Japanese for a link-less match says 検索結果, the set of status kinds that name no site is one predicate shared by the mapping and the panel, and the tests pin the appended next-step clause and the adjacency the 18px rule depends on.
…d for (SONA-220) When a parent move lands on a tile whose lookup is still out, the record of what the move emptied now lives exactly as long as that request: it is consumed when the result lands on the parent, and discarded when the result lands in any other mode, so a later unrelated lookup can never re-report a clearing that was already spoken. The thrown-result path builds its failed state and hands it to the same apply function as every other result, so the cleared record has one writer and one normalisation. The status mapping is a flat switch again, the untagged-and-non-empty test exists once, and the announcements say "the result Sona found" and "the parent image's last lookup" in line with their neighbours.
…e announcements name the last lookup (SONA-220) The panel no longer keeps saying Sona cleared a field once the operator has typed into it: the edited record now covers a field the operator filled that no lookup had touched, and the status kind drops a cleared flag for any field the edited record names. The three parent-move announcements say "the last lookup filled" in both languages, the phrasing the status lines already use and the one that is true on every path. Each settle arm takes the pending record once and hands it to the apply function, the held-URL test is one named value, and the comments on the record's lifetime say exactly which exits drop it.
…talogs (SONA-220)
… screen for what is empty (SONA-220) statusLineKind keeps the raw record of what a result emptied beside the record the operator's typing has neutralised, and routes each question to the right one: whether to claim a field was kept reads history, so a field this result emptied is never called "left as it was"; whether to invite the operator to fill a field reads the screen, so a field they have typed into is never called cleared. A clash over a URL the operator has since typed says the URL was left as it was rather than empty. Once the operator has typed into an emptied field the cleared claim stays down even if they delete the text, so the panel never attributes their own deletion to Sona. A 45-row truth table pins every field state per field for both pages' wordings, each row also checking the sentence claims nothing the screen contradicts.
…he upload form (SONA-220) On the upload form the latch that records the operator typing into an emptied field was lowered only on a parent move, so once raised it survived every later lookup on the same tile and could silence a genuine clearing by a later result. applyShared now recomputes both latches against the result it is applying, so a refill lowers them and the operator's own text keeps them. The seed guard that erased the emptied fact for a refilled field is gone; the latch and the raw flags answer instead, so a field a parent move emptied and the operator retyped is described by the kept sentence rather than as left as it was. The truth table gains a typed-over state and folds its duplicate rows, the markup test pins the recompute site and counts the latch reset at every reset site, and the four-lookup sequences run on both pages.
… the comments say what the code does (SONA-220) While the moved-onto tile's lookup is still out, the panel now shows the same causal-free sentence the live region spoke for the move, chosen by one shared clearedLine mapping so the two channels cannot drift; the emptied sentences with a reason wait for the result that settles it. The comments on the upload form's latch and on sourceHeld name their real readers and the accepted trade for text typed and deleted during a round trip, the seed alias is gone, the four-lookup story is told once, and the two four-lookup end-to-end sequences share one helper.
…220) Now that the panel's searching state carries the move sentence inside its status region, the upload form's announcer speaks only when the new parent has no lookup at all, so the clearing is heard once rather than from two regions in the same tick. clearedLine takes the edited record as a required argument, the markup tests slice the function they inspect instead of counting characters, and the comments quote the shipped sentence.
… a search in flight (SONA-220) Starting a lookup on a parent tile that had none drops the cleared record the move left behind, so the panel's searching state does not repeat a sentence the live region already spoke. The announcer's guard reads the same value the panel renders, so whether a panel exists decides who speaks. The markup tests slice function bodies with one brace-aware helper that survives a multi-line signature, which is what let the onParentChanged assertion pass without reaching the body; each slice now proves it found the function before asserting what it lacks.
…ult's cleared record (SONA-220) The reset was gated on the tile having been idle, so a third lookup on a tile whose no-match had already reported a clearing carried that record into the searching state and spoke it again. A tile that is still searching never reaches this code, so the reset is unconditional on the parent branch; the record for a move that landed on a search in flight lives in the pending record and is unaffected.
◈ PR Lens
Architecture 5 components touched across 5 lanes. Inside the changed components — 2 viewsComponent view — Artist lookup prefill and clearance Internal components coordinating reverse artist lookups, prefill lifecycles, and cleared field status reporting. Component view — Admin form container styling and rating badges CSS container query row styling and rating pill wrapping beside the NSFW checkbox. Data flow
View
Tip Push a commit and the comment redraws for the new head. A slow older run never overwrites a newer one. 🪧 More tips
Thanks for using PR Lens! It's built by Coldtea, free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Essentials Run ID: 📒 Files selected for processing (12)
Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour. 📝 WalkthroughWalkthroughLookup state now records fields cleared by settled artist searches and preserves later operator edits. Upload and edit pages pass this state to localized status rendering. Shared rating rows use container-query layouts. Tests cover lookup transitions, announcements, navigation, and responsive behavior. ChangesArtist lookup state and presentation
Priority: ➖ Normal Estimated code review effort: 4 (Complex) | ~60 minutes Change: Bug fix Merge Risk: ⚪ Minimal · up to This change preserves lookup-prefilled source URLs and commissioned dates across repeat lookups, adds matching English/Japanese status text, and makes the NSFW/rating row responsive to its container width. Prior review passes across all five stack layers found no unresolved correctness or safety issues, and this final pass did not surface a new confirmed defect, so the change appears ready to merge. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Warning Git: CodeRabbit could not clone the repository, so clone-backed analysis was skipped and this review may be incomplete. Verify repository clone access, such as SSH credentials, before requesting another full review. If clone access is intentionally unavailable, use Comment |
|
@coderabbitai full review |
✅ Action performedFull review finished. |
… the machine's monospace (SONA-220)
|
@coderabbitai full review |
✅ Action performedFull review finished. |
Follow-up to #435 and #436. When SONA-156 and SONA-220 met on the upload and edit forms, a repeat artist lookup blanked the source post URL the moment it started, and the tag suggestion control answered that change by dropping its chips. The two rating pills also shared one row in the edit form's 600px column and pushed the "Mark it NSFW" button onto a second line.
What changes
On both forms the source post URL and commissioned date that a lookup filled now stay in place until the next result lands. A result that names the same post leaves them alone. A different post replaces them. A result with nothing to put there clears them. Whatever changes, the panel's status line says so, and the upload form's live region says it only when no panel is on screen to carry it. The panel and the announcer read one mapping from status to sentence, so they cannot disagree about why a field changed.
On the upload form, a parent move onto a tile whose lookup is still out keeps a record of what the move emptied until that result arrives, and drops the record when the request settles in any mode or is cancelled. A field the operator types into is never described as cleared, and the panel never attributes their own deletion to Sona.
The NSFW row on both forms is laid out by the width of its own column rather than the window. Below 560px of column it stacks with a 24px indent. Above that, the two rating pills shrink and wrap so the button stays beside the checkbox. The rating pill has a fixed 12px radius, so a wrapped pill keeps its end caps clear of the text.
Copy
Five new status sentences report that a field the last lookup filled was cleared, and a clash that clears a filled URL gets its own sentence. The three parent-move announcements say "the last lookup filled", the phrasing the status lines already use. English and Japanese carry every key.
Verified
After merge
There is nothing to run: no migration and no setting.