Skip to content

Add StaffTags: internal admin-only tagging for people - #2313

Merged
maebeale merged 16 commits into
mainfrom
maebeale/admin-facilitator-tags
Aug 22, 2026
Merged

Add StaffTags: internal admin-only tagging for people#2313
maebeale merged 16 commits into
mainfrom
maebeale/admin-facilitator-tags

Conversation

@maebeale

Copy link
Copy Markdown
Collaborator

🤖 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)

  • Same shape as topic subscriptions, but opposite intent: staff assessments, not opt-in comms.
  • Kept separate so these sensitive, never-public designations can't leak into any comms/export flow. The privacy boundary is structural (admin-only policy + relation scope), not a retrofitted filter.

Shape

  • StaffTag (admin-curated list) + polymorphic StaffTagging join + StaffTaggable concern (Person today; polymorphic so orgs/events can opt in later).
  • Admin CRUD mirroring category_types, plus archive/unarchive (archive hides from pickers, keeps history; delete blocked while in use).
  • Person edit form: admin-only checkbox section; each tagging records which admin applied it.
  • People index: admin-only "Staff tag" filter → pull a roster of everyone carrying a tag.

Not in this PR (flagged)

  • Public tag-page (/tags, /taggings) browse with admin styling — deferred; the people-index filter already delivers the roster use case.

@maebeale
maebeale marked this pull request as ready for review August 22, 2026 10:30
@maebeale
maebeale requested a review from jmilljr24 August 22, 2026 12:26
@maebeale
maebeale force-pushed the maebeale/admin-facilitator-tags branch from 8909252 to 2ef0515 Compare August 22, 2026 12:34
maebeale and others added 16 commits August 22, 2026 09:07
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>
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.

1 participant