Add StaffTags: internal admin-only tagging for people - #2313
Merged
Conversation
maebeale
marked this pull request as ready for review
August 22, 2026 10:30
maebeale
force-pushed
the
maebeale/admin-facilitator-tags
branch
from
August 22, 2026 12:34
8909252 to
2ef0515
Compare
Staff tags are admin-curated, internal labels for talent pipelines, rosters, and outreach (e.g. potential future trainers, cohort candidates). Modeled on the TopicSubscription shape but kept separate so these sensitive, never-public designations can't leak into any comms/export flow. - StaffTag + polymorphic StaffTagging join + StaffTaggable concern (Person) - Admin-only CRUD (mirrors category_types) with archive/unarchive - Assign on the person form; filter the people index by staff tag Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Model/join/policy/decorator/request specs (incl. person form assignment, people-index filter, archived-tag preservation, and admin gating), the Features & tips seed entry, and AGENTS.md model/concern catalog updates. Tailwind class order normalized on touched views. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…te index counts - Person form: workshop settings now render below the staff tags section - Staff tags index: Active status pill is green (was reading as a red error), tag names/checkboxes use neutral styling instead of the rose identity color - Precompute people-tagged counts in one grouped query (no COUNT per row) The /people index itself has no staff-tag N+1: tags aren't rendered per row, only used by the filter (one dropdown query + one JOIN when applied). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Person form: replace the checkbox grid with a sectors/age-ranges-style chip picker — a '➕ Add staff tag' button reveals a dropdown of the active tags not yet applied, each chip removable. Backed by staff_taggings nested attributes; created_by is stamped from Current.user so the audit survives the switch away from the hand-rolled sync. Staff tags index: tag name links straight to the edit screen; dropped the per-row Edit/Archive buttons (archive/unarchive now live on the edit form). The 'People tagged' count already deep-links to the filtered people index with the tag pre-selected in the filter dropdown (result_src carries the query string; the select reads the same param). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Person-form staff tags panel goes back to the admin-only bg-blue-100 treatment; staff tags index inner card is a clean white card on the blue admin wrapper. Removes the now-unused :staff_tags rose entry from DomainTheme. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ings - Show/edit pages render the shared audit_info (created/updated by + Ahoy link) - StaffTag show lists each tagging with who applied it and when - StaffTagging gains updated_by (stamped from Current.user alongside created_by) Note: all models are already Ahoy-tracked via ApplicationRecord, so the audit partial's activity link resolves for these too — no opt-in needed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add StaffTag::SEED (the pipeline/roster/outreach tags we've been building around) and seed them idempotently in db/seeds.rb via find_or_create_by_name! so it never overwrites an admin's edits. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…omments - StaffTag uses the Publishable concern (published boolean) like sectors and categories; drops archived_at, the archive/unarchive actions/routes, and the bespoke scopes. Managed via a published visibility flag on the edit form. - Status reads Published/Unpublished; pickers offer published tags, an already-applied unpublished tag stays on its chip. - Pare back the explanatory comments across the staff-tag code to the few load-bearing 'why' lines. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both /tags and /taggings gain an admin-only Staff tags section (blue admin styling) listing published tags as chips that deep-link to the filtered people roster. Gated by StaffTagPolicy — the relation scope returns none for anyone but super-admins, so the section is invisible to public visitors. Kept it a link-out to the existing people filter rather than wiring a Person-only case into TaggingSearchService. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ntry points The people index now renders a back link that adapts to where the roster was opened from — the staff tags index (← Staff tags), a tag's detail page (← <tag name>), or the Tags/Taggings browse sections — via a return_to param on each originating link. Also trims the staff tags index subtitle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…otes form Two-column md:grid-cols-4 layout — name/description on the left, the published visibility panel on the right instead of stacked full-width below. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a staff_tag_published visibility definition (Offered in the tag pickers / admin-only either way) instead of the generic 'Visible to signed-in users' copy, which was misleading for these admin-only tags. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove the restating comments (relation_scope note, grouped-query note, model headers, the eyebrow/collection notes) per the default-to-no-comment style. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Inline the starter-tag hash where it's seeded rather than as a model constant. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the back-to-index link to a left-aligned '← Staff tags' arrow on the show/edit/new pages (was a right-aligned Home/Staff tags/… cluster), matching the people-index back-nav. Keep the page's own action (Edit / View) on the right. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
maebeale
force-pushed
the
maebeale/admin-facilitator-tags
branch
from
August 22, 2026 13:08
2ef0515 to
12180b7
Compare
This was referenced Aug 22, 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.
🤖 suggested review level: 5 Inspect 🔬 new model + polymorphic join + admin CRUD + person form/filter integration
What
Adds StaffTags — internal, admin-only labels for people (talent pipelines, rosters, outreach). Examples: potential future trainer, sector leader candidate, highlight roster, DV Leadership Cohort, Foster Care Roundtable outreach.
Why a dedicated model (not Category / TopicSubscription reuse)
Shape
StaffTag(admin-curated list) + polymorphicStaffTaggingjoin +StaffTaggableconcern (Person today; polymorphic so orgs/events can opt in later).category_types, plus archive/unarchive (archive hides from pickers, keeps history; delete blocked while in use).Not in this PR (flagged)
/tags,/taggings) browse with admin styling — deferred; the people-index filter already delivers the roster use case.