Skip to content

JM: Capture sector "Other" free-text as records; curate (promote/keep/dismiss)#1939

Draft
maebeale wants to merge 3 commits into
mainfrom
maebeale/hide-sector-other-from-profile
Draft

JM: Capture sector "Other" free-text as records; curate (promote/keep/dismiss)#1939
maebeale wants to merge 3 commits into
mainfrom
maebeale/hide-sector-other-from-profile

Conversation

@maebeale

@maebeale maebeale commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

🤖 suggested review level: 5 Inspect 🔬 new model + registration capture path + profile/edit display swaps + admin review page whose promote/keep/dismiss actions transform tags across many people

Why

Free-text "Other" sectors people type on registration forms were derived on the fly from form answers and shown as read-only chips — with nowhere to record a curation decision, and no way to hide one that shouldn't appear on the public profile.

What

  • OtherResponse model materializes each person's typed "Other" (kind: "sector" now; column leaves room for workshop settings later). Statuses: pendingpromoted / kept / dismissed.
  • Capture at registration (PublicRegistration), de-duped per person. No backfill — there are no existing public registrations.
  • Profile + person-edit render the visible (pending/kept) responses; the edit chip gains an × that dismisses (hides from profile + edit). The registration submission view is left untouched (it's the audit record).
  • Admin review page (/other_responses, linked from the Sectors index): groups the same value across people with a count, filterable by All / Pending / Kept. Per group:
    • Promote → map to an existing sector or mint a new published one, tag every non-dismissed person, mark them promoted.
    • Keep all / Dismiss all → bulk-set the group's status.

Decisions baked in

  • Dismissed wins: a promoted value does not re-tag people who dismissed it.
  • Promote to a new sector creates a published Sector (not added to the SECTOR_TYPES seed constant — DB is source of truth).
  • kept responses stay visible in the review queue (filter to hide them) rather than dropping off.

Tests

Model, registration capture (request), profile/edit rendering + dismiss, and the review page (index, filter, dismiss, bulk keep/dismiss, promote incl. new-sector minting).

Rebased on main

Resolved conflicts with #1872 (age-range editor restructured the person form/profile — took its layout, kept the renamed other_sector_responses partial) and confirmed coexistence with #1875 (org agency_type_other, a separate concern).

Copilot AI review requested due to automatic review settings July 5, 2026 01:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

# they can be curated (promoted/kept/dismissed). Reuses OtherOption.texts, the
# same extraction used to display them, and de-dupes on the person's normalized
# value so a repeat registration of the same text doesn't create a second row.
def capture_other_sector_responses(submission)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 From Claude: Capture reuses OtherOption.texts (the same extraction the display used) and find_or_create_by on the person + normalized value, so a repeat registration of the same "Other" text doesn't create a second row or trip the unique index.

sector = target_sector
return redirect_to other_responses_path, alert: "Pick or name a sector to promote to." unless sector

responses = OtherResponse.sectors.promotable_now

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 From Claude: promotable_now excludes dismissed — so "dismissed wins": promoting a value never re-tags someone who deliberately hid it.

<%= response.text %>
<span class="ml-1 text-xs text-gray-400">(other)</span>
<% if dismissable %>
<%= link_to "×",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 From Claude: Dismiss is a link_to with turbo_method: :patch, not button_to — this chip lives inside the person edit <form>, and a nested <form> (what button_to emits) is invalid HTML.

maebeale and others added 3 commits July 4, 2026 22:53
Free-text "Other" sector values were derived on the fly from form answers and
shown as read-only chips with nowhere to hang a curation decision. Materialize
them as records so a curator can promote a recurring value into a real Sector,
keep it as a free-text chip, or dismiss it (hide from profile/edit).

Data layer only: migration, model, factory, specs. `kind` leaves room for the
identical workshop-setting responses to migrate here later.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Capture free-text "Other" sector answers as OtherResponse records at
  registration time (PublicRegistration), de-duped per person.
- Person#other_sector_responses now reads the visible (pending/kept) records;
  profile + edit render them via a records-based partial. The edit chip gains an
  × that dismisses (hides) a response. Submission view is untouched (audit).
- Admin review page (/other_responses) groups the same value across people with
  a count; promote maps them all to an existing sector or mints a new published
  one and tags every non-dismissed person. Reachable from the Sectors index.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The review page could only promote; add Keep all / Dismiss all bulk actions per
grouped value, and a status filter (All / Pending / Kept) so kept responses stay
visible in the queue but can be filtered out.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@maebeale maebeale force-pushed the maebeale/hide-sector-other-from-profile branch from f22fbe8 to 1b3fb0f Compare July 5, 2026 02:58
Copilot AI review requested due to automatic review settings July 5, 2026 02:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.


# Bulk keep/dismiss every visible person who typed this value, from the review
# queue. Keep leaves it as a free-text chip; dismiss hides it from profiles.
def curate

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 From Claude: Bulk keep/dismiss acts on the whole grouped value (all VISIBLE_STATUSES rows for this normalized_text), mirroring how promote fans out across everyone who typed it. return_status round-trips the active filter so the queue stays put after the action.

@maebeale maebeale marked this pull request as ready for review July 5, 2026 03:06
@maebeale maebeale changed the title Capture sector "Other" free-text as records; curate (promote/keep/dismiss) JM: Capture sector "Other" free-text as records; curate (promote/keep/dismiss) Jul 5, 2026
@maebeale

maebeale commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator Author

what we have now on profile w form submission data is super brittle. this would allow us to capture all form 'other' answer data and decide if it gets promoted, wiped, or kept as auxiliary data.

@maebeale maebeale marked this pull request as draft July 5, 2026 03:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants