dreamteamprod / dreamteamprod/DigiScript
Add per-character eligible cast pool and per-session casting matrix
Nobody has claimed this yet.
- Dominant language
- Vue
- Stars
- 19
- Forks
- 4
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 37
Description
Summary
Characters currently have a single played_by link to a cast member. This adds:
- An ordered eligible cast pool per character (principal + understudies/covers)
- A new Casting page — a character × session matrix where each cell records who plays that character for a given performance
- Scheduling a session (from #1112) auto-seeds the matrix with all-principal cast; cells can be edited to assign covers
Part 2 of 3 for issue #792. Depends on #1112 (session scheduling).
Backend changes
New model CharacterEligibleCast (server/models/show.py):
class CharacterEligibleCast(db.Model):
__tablename__ = "character_eligible_cast"
character_id: Mapped[int] = mapped_column(ForeignKey("character.id", ondelete="CASCADE"), primary_key=True)
cast_id: Mapped[int] = mapped_column(ForeignKey("cast.id", ondelete="CASCADE"), primary_key=True)
priority: Mapped[int] = mapped_column(default=0) # 0 = principal, ascending = covers
Add eligible_cast relationship to Character (ordered by priority).
New model SessionCasting (server/models/session.py):
class SessionCasting(db.Model):
__tablename__ = "session_casting"
session_id: Mapped[int] = mapped_column(ForeignKey("showsession.id", ondelete="CASCADE"), primary_key=True)
character_id: Mapped[int] = mapped_column(ForeignKey("character.id", ondelete="CASCADE"), primary_key=True)
cast_id: Mapped[int] = mapped_column(ForeignKey("cast.id", ondelete="RESTRICT"))
Add casting relationship to ShowSession.
Alembic migration: alembic revision --autogenerate -m "add_eligible_cast_and_session_casting" — include data migration: each Character.played_by → CharacterEligibleCast(priority=0). Also update SessionStartController from #1112 to seed SessionCasting rows for all characters using priority-0 cast when a session is started/created.
Schema updates: CharacterSchema → add eligible_cast; ShowSessionSchema → add casting; new SessionCastingSchema, CharacterEligibleCastSchema.
New endpoints:
| Method | Path | Role | Description |
|---|---|---|---|
GET |
/api/v1/show/characters/{id}/eligible-cast |
READ | Ordered eligible cast list |
PUT |
/api/v1/show/characters/{id}/eligible-cast |
WRITE | Replace entire list. Body: {cast_ids: [ordered]}. Syncs Character.played_by to cast_ids[0]. |
GET |
/api/v1/show/sessions/{id}/casting |
READ | All SessionCasting rows for a session |
PATCH |
/api/v1/show/sessions/{id}/casting |
WRITE | Bulk-update. Body: [{character_id, cast_id}]. 409 if session already started. Validates cast_id is in eligible pool. |
Frontend changes (client-v3/)
New route: show-config-casting → ConfigCasting.vue
New nav item in ShowConfigView.vue (between Characters and Mics): Casting
New components (components/show/config/casting/):
ConfigCasting.vue— page; "Preparing for:" session picker; containsCastingMatrix.vue; showsMicPlanStaleBanner.vuewhen active session has any non-principal castCastingMatrix.vue— horizontal-scroll table; sticky "Character" + "Eligible Cast" columns; one column per session; active column green-tinted; cover cells amber-tinted; click cell →CastPickerDropdown.vueCastPickerDropdown.vue— eligible cast list with PRINCIPAL badge; "↺ Reset to principal"; "+ Add cast to eligible pool…"EligibleCastChips.vue— chip per eligible cast member; × to remove non-principals; "+ Cover" add buttonMicPlanStaleBanner.vue(stub) — amber bar: "Casting changes may require a mic re-run. Review on Mics →"
ConfigCharacters.vue — add "Eligible Cast" column showing EligibleCastChips; eligible cast section in edit modal.
ConfigSessions.vue (from #1112) — add "Cast" action button → navigates to casting page for that session; extend start-session confirmation to show full cast roster table.
stores/show.ts additions:
- State:
sessionCasting: Record<string, SessionCasting[]>,characterEligibleCast: Record<string, EligibleCast[]> - Actions:
getSessionCasting,updateSessionCasting,getCharacterEligibleCast,updateCharacterEligibleCast - Getter:
castDiffForSession(sessionId): CastDiff[]— compares session casting vs each character's priority-0 cast
New src/types/api/casting.ts:
interface EligibleCast { character_id: number; cast_id: number; priority: number }
interface SessionCasting { session_id: number; character_id: number; cast_id: number }
interface CastDiff { character_id: number; character_name: string; principal_cast_id: number; session_cast_id: number }
E2E tests
New client-v3/e2e/tests/12b-show-config-casting.spec.ts:
- Verify "Casting" nav item visible
- Matrix shows characters × sessions
- Click cell → pick cover → amber highlight
- Add eligible cast via "+ Cover"
- Stale mic banner appears after cover selection
- Banner links to Mics page
Update 12-show-config-sessions.spec.ts:
- "Cast" button navigates to Casting page
- Start-session confirmation shows cast roster
Notes
Character.played_byis kept for backward compatibility;PUT /eligible-castkeeps it in sync with priority-0 cast.- Once
start_date_timeis set on a session,PATCH /sessions/{id}/castingreturns 409. Frontend disables cell editing for started/completed sessions. - Casting is not shown in the live show view.
Verification
pytest— new tests for eligible cast and session casting endpointsnpm run typecheck+npm run lintnpm run test:e2e— full suite
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with server/models/show.py, server/models/session.py, and the SessionStartController changes from #1112, then inspect the related client-v3 configuration views and stores. Verify the migration, schemas, endpoints, casting matrix, and session navigation against the listed pytest, typecheck, lint, and E2E checks; done means eligible pools and per-session casting work end to end.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, sqlalchemy, typescript
- Domain
- api, backend, database, frontend, full-stack, testing
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 32/100