Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4b793e3
New attempt at hearing backend
delexagon May 26, 2026
3dd28e2
Fastforward to main
delexagon Jun 2, 2026
9389560
Prettier
delexagon Jun 2, 2026
d227c5f
Small fixes
delexagon Jun 2, 2026
80fa337
Video title parsing
delexagon Jun 2, 2026
fa46b20
Allowed to reuse existing transcripts
delexagon Jun 2, 2026
5569394
Prettier
delexagon Jun 2, 2026
e135a15
Rewrote additional files
delexagon Jun 3, 2026
f449912
Small bugfixing
delexagon Jun 3, 2026
76f7afb
Align to Assembly AI return
delexagon Jun 10, 2026
88df8e8
Prettier
delexagon Jun 10, 2026
09ee0bc
Fixing simple bugs
delexagon Jun 17, 2026
8491a58
Moved removeCommonWords to helpers.ts
delexagon Jun 22, 2026
6d5c9a1
Cross-compatibility
delexagon Jun 24, 2026
083cc71
Additional fixes
delexagon Jun 24, 2026
291ddb4
Fast-forward past cross-compatibility commit
delexagon Jun 24, 2026
542b448
Prettier
delexagon Jun 24, 2026
2b62740
Fixed bug with recreate-transcripts
delexagon Jul 1, 2026
e08a436
Fixed bug with migrateHearingTranscription
delexagon Jul 1, 2026
5ec6a3c
Prettier
delexagon Jul 1, 2026
56d8f1a
Single file submitTranscription
delexagon Jul 1, 2026
4ce4d44
Rewrite to stepwise save transcription ids
delexagon Jul 7, 2026
4eb0739
Multi video limit
delexagon Jul 8, 2026
4135a67
Bugfix, remove writer
delexagon Jul 8, 2026
fac5a3c
Merge branch 'main' into multi-video-backend
delexagon Jul 8, 2026
e555042
Bugfixes
delexagon Jul 8, 2026
2325fb0
Merge
delexagon Jul 8, 2026
0b1eeaa
Error for unset FUNCTIONS_API_BASE
delexagon Jul 15, 2026
be3c2d9
Rewrite error
delexagon Jul 15, 2026
e8f9c7d
scrapeSingleHearing user warning
delexagon Jul 15, 2026
1be30d5
Removed necessary mutation from getHearingVideos
delexagon Jul 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions components/ballotquestions/CommitteeHearing.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,43 @@ describe("CommitteeHearing", () => {
})

it("shows hearing context copy", () => {
render(<CommitteeHearing hearing={{ id: "1", startsAt: FUTURE_MS }} />)
render(
<CommitteeHearing
hearing={{ id: "1", startsAt: FUTURE_MS, videoURLs: [] }}
/>
)
expect(screen.getByText("Committee Hearing")).toBeInTheDocument()
expect(
screen.getByText("Committee hearings are public meetings.")
).toBeInTheDocument()
})

it("formats the hearing date", () => {
render(<CommitteeHearing hearing={{ id: "1", startsAt: PAST_MS }} />)
render(
<CommitteeHearing
hearing={{ id: "1", startsAt: PAST_MS, videoURLs: [] }}
/>
)
expect(screen.getByText(/December 14, 2025/)).toBeInTheDocument()
})

it("shows a hearing page link when an id is present", () => {
render(
<CommitteeHearing hearing={{ id: "hearing-1", startsAt: PAST_MS }} />
<CommitteeHearing
hearing={{ id: "hearing-1", startsAt: PAST_MS, videoURLs: [] }}
/>
)
expect(
screen.getByRole("link", { name: /Open hearing page/i })
).toHaveAttribute("href", "/hearing/1")
})

it("hides the hearing page link when no hearing id is available", () => {
render(<CommitteeHearing hearing={{ id: "", startsAt: PAST_MS }} />)
render(
<CommitteeHearing
hearing={{ id: "", startsAt: PAST_MS, videoURLs: [] }}
/>
)
expect(screen.queryByRole("link")).not.toBeInTheDocument()
})
})
2 changes: 1 addition & 1 deletion components/ballotquestions/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export type Hearing = {
id: string
videoURL?: string
videoURLs: string[]
startsAt: number // milliseconds since epoch, converted from Firestore Timestamp server-side
}

Expand Down
6 changes: 3 additions & 3 deletions docs/ballot-questions-frontend.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,15 @@ For each relevant hearing, display:

- **Status**: "Occurred" if `hearing.content.startsAt` is in the past, "Scheduled" if in the future
- **Date**: formatted from `hearing.content.startsAt`
- **Watch link**: "Watch the committee hearing here." linked to `hearing.videoURL` — hidden if no video
- **Watch link**: "Watch the committee hearing here." linked to `hearing.videoURLs` — hidden if no videos

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If we're linking to a hearing, we should probably just link to the /hearing/<HEARING_ID> page on the MAPLE site. Even if we do link to the legislature, we should link to the hearing page, not directly to the videoURL.

(Not directly relevant here - more a statement about how we shouldn't invest too many calories into making the Ballot Questions' Hearing type support multiple video URLs - at most, I suspect we'll want to link to the "first" video)

@delexagon delexagon Jun 17, 2026

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.

I noticed this discrepancy at my end check for any uses of videoURL - I don't know what the ballot page looks like & the videoURL field does not currently appear to be used. I will fully defer to your judgement on how we want to address this. To be honest, I more meant this as a signal to the contractors working on the ballot questions that there are now multiple videos per hearing, and let them handle that how they will.


Since ballot questions are always under SJ42 and typically have one hearing, render a single hearing block. If there are multiple, render them in reverse chronological order (most recent first).

**Hearing data model recap:**

- `bill.hearingIds?: string[]` — event IDs; doc path is `/events/hearing-{id}`
- `bill.nextHearingAt?: Timestamp` — convenience field for upcoming hearing only (not sufficient alone — we need date + videoURL from the full document)
- `hearing.videoURL?: string` — link for the "Watch" CTA
- `bill.nextHearingAt?: Timestamp` — convenience field for upcoming hearing only (not sufficient alone — we need date + videoURLs from the full document)
- `hearing.videoURLs: string[]` — link for the "Watch" CTA
- `hearing.content.startsAt` — determines "Occurred" vs. "Scheduled" status

No new components are needed for hearing display — build a simple `CommitteeHearing` component local to `components/ballotquestions/`.
Expand Down
Loading
Loading