From 1d32754f76be0d3bc17b7eb4241f5f1baded2cbe Mon Sep 17 00:00:00 2001 From: Mephistic Date: Tue, 8 Sep 2026 18:28:47 -0400 Subject: [PATCH 1/6] feat: Add individual hearing page that uses the Hearings API - just getting a front-end on this to test the quality of transcripts for now --- .env.example | 1 + components/bootstrap.ts | 1 + components/hearing/DDHearingDetails.tsx | 121 ++++++++++++++++++++++ components/hearing/digitalDemocracyApi.ts | 87 ++++++++++++++++ pages/api/hearings/[hid]/utterances.ts | 28 +++++ pages/hearings/[hid].tsx | 45 ++++++++ public/locales/en/hearing.json | 1 + 7 files changed, 284 insertions(+) create mode 100644 components/hearing/DDHearingDetails.tsx create mode 100644 components/hearing/digitalDemocracyApi.ts create mode 100644 pages/api/hearings/[hid]/utterances.ts create mode 100644 pages/hearings/[hid].tsx diff --git a/.env.example b/.env.example index 25add1752..ddd0f5698 100644 --- a/.env.example +++ b/.env.example @@ -2,3 +2,4 @@ TEST_ADMIN_USERNAME=your_admin_email@example.com TEST_ADMIN_PASSWORD=your_admin_password APP_API_URL=http://localhost:3000 +DIGITAL_DEMOCRACY_API_KEY=your_digital_democracy_api_key diff --git a/components/bootstrap.ts b/components/bootstrap.ts index 1fa768584..f231fb79b 100644 --- a/components/bootstrap.ts +++ b/components/bootstrap.ts @@ -4,6 +4,7 @@ export { default as Alert } from "react-bootstrap/Alert" export { default as Badge } from "react-bootstrap/Badge" export { default as Button } from "react-bootstrap/Button" export { default as Card } from "react-bootstrap/Card" +export { default as Carousel } from "react-bootstrap/Carousel" export { default as Col } from "react-bootstrap/Col" export { default as Collapse } from "react-bootstrap/Collapse" export { default as Container } from "react-bootstrap/Container" diff --git a/components/hearing/DDHearingDetails.tsx b/components/hearing/DDHearingDetails.tsx new file mode 100644 index 000000000..34926afff --- /dev/null +++ b/components/hearing/DDHearingDetails.tsx @@ -0,0 +1,121 @@ +import { useTranslation } from "next-i18next" +import { useEffect, useState } from "react" +import styled from "styled-components" +import { Carousel, Col, Container, Row } from "../bootstrap" +import { Back } from "../shared/CommonComponents" +import { + DDHearing, + DDUtterance, + speakerName +} from "./digitalDemocracyApi" + +const VideoWrapper = styled.div` + max-width: 700px; + margin: 0 auto; +` + +/* padding-top % is relative to VideoWrapper's width, so max-width must live there, not here */ +const VideoParent = styled.div` + position: relative; + width: 100%; + padding-top: 56.25%; /* For 16:9 aspect ratio */ + overflow: hidden; +` + +const VideoChild = styled.video` + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: none; +` + +const TranscriptContainer = styled(Container)` + background-color: var(--maple-surface-base); +` + +const TranscriptRow = styled(Row)` + &:nth-child(even) { + background-color: white; + } + &:nth-child(odd) { + background-color: var(--maple-surface-transcript-stripe); + } +` + +const Speaker = styled.div` + font-weight: 600; + color: var(--maple-text-strong); +` + +export const DDHearingDetails = ({ hearing }: { hearing: DDHearing }) => { + const { t } = useTranslation(["common", "hearing"]) + const [utterances, setUtterances] = useState(null) + + useEffect(() => { + let cancelled = false + ;(async function () { + const res = await fetch(`/api/hearings/${hearing.hid}/utterances`) + if (!res.ok || cancelled) return + const body: { utterances: DDUtterance[] } = await res.json() + if (!cancelled) setUtterances(body.utterances) + })() + return () => { + cancelled = true + } + }, [hearing.hid]) + + const videos = [...hearing.hearing_videos].sort( + (a, b) => (a.start_time ?? a.uid) - (b.start_time ?? b.uid) + ) + + return ( + + + + {t("back_to_hearings")} + + + +

{hearing.title}

+ + {videos.length > 0 ? ( + 1} + controls={videos.length > 1} + > + {videos.map(video => ( + + + + + + + + ))} + + ) : null} + + + {utterances === null ? ( +
+ {t("transcript_loading", { ns: "hearing" })} +
+ ) : ( + utterances.map(utterance => ( + + + {speakerName(utterance) ?? + t("unknown_speaker", { ns: "hearing" })} + +
{utterance.content}
+
+ )) + )} +
+
+ ) +} diff --git a/components/hearing/digitalDemocracyApi.ts b/components/hearing/digitalDemocracyApi.ts new file mode 100644 index 000000000..de288629a --- /dev/null +++ b/components/hearing/digitalDemocracyApi.ts @@ -0,0 +1,87 @@ +const API_KEY = process.env.DIGITAL_DEMOCRACY_API_KEY ?? "" + +const BASE_URL = "https://api.digitaldemocracy.org" + +export type DDHearingVideo = { + file_id: string + uid: number + video_url: string + // Not present on all responses; falls back to `uid` ordering when absent. + start_time?: number +} + +export type DDHearing = { + hid: number + title: string + date: string + session_year: string + state: string + hearing_video_thumbnail: string | null + hearing_videos: DDHearingVideo[] +} + +type DDHearingResponse = { + data: { + hearing: DDHearing + agenda: unknown[] + } +} + +export type DDUtterance = { + content: string + first: string | null + last: string | null + person_type: string + pid: number | null + hid: number + uid: number + file_id: string + timestamp: number + date: number +} + +type DDUtterancesResponse = { + data: { + utterances: DDUtterance[] + } + page: number + per_page: number + total_pages: number + total_results: number +} + +function headers() { + return { "x-api-key": API_KEY } +} + +export async function fetchDDHearing( + hid: string | number +): Promise { + const res = await fetch(`${BASE_URL}/legacy/ma/hearing/${hid}`, { + headers: headers() + }) + if (!res.ok) return null + + const body: DDHearingResponse = await res.json() + return body.data?.hearing ?? null +} + +export async function fetchDDUtterances( + hid: string | number +): Promise { + const res = await fetch( + `${BASE_URL}/legacy/ma/elasticsearch/utterances?hid=${hid}&per_page=500`, + { headers: headers() } + ) + if (!res.ok) return [] + + const body: DDUtterancesResponse = await res.json() + const utterances = body.data?.utterances ?? [] + return [...utterances].sort((a, b) => a.timestamp - b.timestamp) +} + +export function speakerName(utterance: DDUtterance): string | null { + const { first, last } = utterance + if (!first && !last) return null + return [first, last].filter(Boolean).join(" ") +} diff --git a/pages/api/hearings/[hid]/utterances.ts b/pages/api/hearings/[hid]/utterances.ts new file mode 100644 index 000000000..a46f6dc8e --- /dev/null +++ b/pages/api/hearings/[hid]/utterances.ts @@ -0,0 +1,28 @@ +import { NextApiRequest, NextApiResponse } from "next" +import { z } from "zod" +import { fetchDDUtterances } from "components/hearing/digitalDemocracyApi" + +const QuerySchema = z.object({ hid: z.coerce.number() }) + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + if (req.method !== "GET") { + res.status(404).end() + return + } + + const query = QuerySchema.safeParse(req.query) + if (!query.success) { + res.status(400).json({ error: "Invalid hid" }) + return + } + + const utterances = await fetchDDUtterances(query.data.hid) + res.setHeader( + "Cache-Control", + "public, s-maxage=3600, stale-while-revalidate=3600" + ) + res.status(200).json({ utterances }) +} diff --git a/pages/hearings/[hid].tsx b/pages/hearings/[hid].tsx new file mode 100644 index 000000000..5fa569f8a --- /dev/null +++ b/pages/hearings/[hid].tsx @@ -0,0 +1,45 @@ +import { GetServerSideProps } from "next" +import { serverSideTranslations } from "next-i18next/serverSideTranslations" +import { z } from "zod" +import { createPage } from "../../components/page" +import { DDHearingDetails } from "components/hearing/DDHearingDetails" +import { + DDHearing, + fetchDDHearing +} from "components/hearing/digitalDemocracyApi" + +const Query = z.object({ hid: z.coerce.number() }) + +export default createPage<{ hearing: DDHearing }>({ + titleI18nKey: "navigation.hearing", + Page: ({ hearing }) => { + return + } +}) + +export const getServerSideProps: GetServerSideProps = async ctx => { + ctx.res.setHeader( + "Cache-Control", + "public, s-maxage=3600, stale-while-revalidate=3600" + ) + + const locale = ctx.locale ?? ctx.defaultLocale ?? "en" + + const query = Query.safeParse(ctx.query) + if (!query.success) return { notFound: true } + + const hearing = await fetchDDHearing(query.data.hid) + if (!hearing) return { notFound: true } + + return { + props: { + hearing, + ...(await serverSideTranslations(locale, [ + "auth", + "common", + "footer", + "hearing" + ])) + } + } +} diff --git a/public/locales/en/hearing.json b/public/locales/en/hearing.json index bfd82a69c..48f1c2087 100644 --- a/public/locales/en/hearing.json +++ b/public/locales/en/hearing.json @@ -28,6 +28,7 @@ "see_less": "See less", "senate_chair": "Senate Chair", "transcript_loading": "Loading transcript for this hearing...", + "unknown_speaker": "Unknown speaker", "video_and_transcription_feature_callout": "Hearing Video + Transcription", "view_bill": "View Bill Details", "view_votes": "View Committee Votes", From 3f941707824617b698bf32c1b7d64f6dcbc2850c Mon Sep 17 00:00:00 2001 From: Mephistic Date: Tue, 8 Sep 2026 18:46:07 -0400 Subject: [PATCH 2/6] testing: Use a static map of the unique speakers to map legislators from the DD API with member legislators from the MA Legislature API. These 10 were selected manually just for testing purposes - for production, we would need to work out this mapping for all legislators --- components/hearing/DDHearingDetails.tsx | 46 ++++++++++++++++++++----- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/components/hearing/DDHearingDetails.tsx b/components/hearing/DDHearingDetails.tsx index 34926afff..febb1e013 100644 --- a/components/hearing/DDHearingDetails.tsx +++ b/components/hearing/DDHearingDetails.tsx @@ -3,12 +3,26 @@ import { useEffect, useState } from "react" import styled from "styled-components" import { Carousel, Col, Container, Row } from "../bootstrap" import { Back } from "../shared/CommonComponents" +import { Internal } from "../links" import { DDHearing, DDUtterance, speakerName } from "./digitalDemocracyApi" +const ddApiPersonIdToMemberId: Record = { + 211022: "PRF0", // Paul Feeney + 211000: "MSD1", // Michael Day + 211028: "RCF0", // Ryan Fattman + 210993: "K_H1", // Kate Hogan + 210961: "DTV1", // David Vieira + 210945: "CFF0", // Cindy Friedman + 210928: "BRF0", // Barry Finegold + 210931: "BPC0", // Brendan Crighton + 210924: "AHP1", // Alice Peisch + 210964: "FAM1", // Frank Moran +} + const VideoWrapper = styled.div` max-width: 700px; margin: 0 auto; @@ -105,15 +119,29 @@ export const DDHearingDetails = ({ hearing }: { hearing: DDHearing }) => { {t("transcript_loading", { ns: "hearing" })} ) : ( - utterances.map(utterance => ( - - - {speakerName(utterance) ?? - t("unknown_speaker", { ns: "hearing" })} - -
{utterance.content}
-
- )) + utterances.map(utterance => { + const name = + speakerName(utterance) ?? t("unknown_speaker", { ns: "hearing" }) + const memberId = + utterance.person_type === "legislator" && utterance.pid !== null + ? ddApiPersonIdToMemberId[utterance.pid] + : undefined + + return ( + + + {memberId ? ( + + {name} + + ) : ( + name + )} + +
{utterance.content}
+
+ ) + }) )} From 2b6b0356e0afb7d794afbbe8e9cdca3768029cf5 Mon Sep 17 00:00:00 2001 From: Mephistic Date: Tue, 8 Sep 2026 18:53:42 -0400 Subject: [PATCH 3/6] Adding hearing committee sidebar (hard-coded for testing) and a scroll to the transcipts box --- components/hearing/DDHearingDetails.tsx | 124 ++++++++++++++---------- 1 file changed, 74 insertions(+), 50 deletions(-) diff --git a/components/hearing/DDHearingDetails.tsx b/components/hearing/DDHearingDetails.tsx index febb1e013..3123aa3fb 100644 --- a/components/hearing/DDHearingDetails.tsx +++ b/components/hearing/DDHearingDetails.tsx @@ -4,12 +4,17 @@ import styled from "styled-components" import { Carousel, Col, Container, Row } from "../bootstrap" import { Back } from "../shared/CommonComponents" import { Internal } from "../links" +import { HearingSidebar } from "./HearingSidebar" import { DDHearing, DDUtterance, speakerName } from "./digitalDemocracyApi" +// Hardcoded for hearing 279802 for testing; production needs a real hid -> committee/general court lookup +const COMMITTEE_CODE = "SJ42" +const GENERAL_COURT_NUMBER = "194" + const ddApiPersonIdToMemberId: Record = { 211022: "PRF0", // Paul Feeney 211000: "MSD1", // Michael Day @@ -47,6 +52,8 @@ const VideoChild = styled.video` const TranscriptContainer = styled(Container)` background-color: var(--maple-surface-base); + max-height: 500px; + overflow-y: auto; ` const TranscriptRow = styled(Row)` @@ -94,56 +101,73 @@ export const DDHearingDetails = ({ hearing }: { hearing: DDHearing }) => {

{hearing.title}

- {videos.length > 0 ? ( - 1} - controls={videos.length > 1} - > - {videos.map(video => ( - - - - - - - - ))} - - ) : null} - - - {utterances === null ? ( -
- {t("transcript_loading", { ns: "hearing" })} -
- ) : ( - utterances.map(utterance => { - const name = - speakerName(utterance) ?? t("unknown_speaker", { ns: "hearing" }) - const memberId = - utterance.person_type === "legislator" && utterance.pid !== null - ? ddApiPersonIdToMemberId[utterance.pid] - : undefined - - return ( - - - {memberId ? ( - - {name} - - ) : ( - name - )} - -
{utterance.content}
-
- ) - }) - )} -
+ + + {videos.length > 0 ? ( + 1} + controls={videos.length > 1} + > + {videos.map(video => ( + + + + + + + + ))} + + ) : null} + + + {utterances === null ? ( +
+ {t("transcript_loading", { ns: "hearing" })} +
+ ) : ( + utterances.map(utterance => { + const name = + speakerName(utterance) ?? + t("unknown_speaker", { ns: "hearing" }) + const memberId = + utterance.person_type === "legislator" && + utterance.pid !== null + ? ddApiPersonIdToMemberId[utterance.pid] + : undefined + + return ( + + + {memberId ? ( + + {name} + + ) : ( + name + )} + +
{utterance.content}
+
+ ) + }) + )} +
+ + +
+ +
+
) } From 28edc471d82fe807223705f26e51914f463b6eae Mon Sep 17 00:00:00 2001 From: Mephistic Date: Tue, 8 Sep 2026 19:12:30 -0400 Subject: [PATCH 4/6] fix(prettier): run prettier --- components/hearing/DDHearingDetails.tsx | 26 +++++++++++-------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/components/hearing/DDHearingDetails.tsx b/components/hearing/DDHearingDetails.tsx index 3123aa3fb..c9b4e1177 100644 --- a/components/hearing/DDHearingDetails.tsx +++ b/components/hearing/DDHearingDetails.tsx @@ -5,27 +5,23 @@ import { Carousel, Col, Container, Row } from "../bootstrap" import { Back } from "../shared/CommonComponents" import { Internal } from "../links" import { HearingSidebar } from "./HearingSidebar" -import { - DDHearing, - DDUtterance, - speakerName -} from "./digitalDemocracyApi" +import { DDHearing, DDUtterance, speakerName } from "./digitalDemocracyApi" // Hardcoded for hearing 279802 for testing; production needs a real hid -> committee/general court lookup const COMMITTEE_CODE = "SJ42" const GENERAL_COURT_NUMBER = "194" const ddApiPersonIdToMemberId: Record = { - 211022: "PRF0", // Paul Feeney - 211000: "MSD1", // Michael Day - 211028: "RCF0", // Ryan Fattman - 210993: "K_H1", // Kate Hogan - 210961: "DTV1", // David Vieira - 210945: "CFF0", // Cindy Friedman - 210928: "BRF0", // Barry Finegold - 210931: "BPC0", // Brendan Crighton - 210924: "AHP1", // Alice Peisch - 210964: "FAM1", // Frank Moran + 211022: "PRF0", // Paul Feeney + 211000: "MSD1", // Michael Day + 211028: "RCF0", // Ryan Fattman + 210993: "K_H1", // Kate Hogan + 210961: "DTV1", // David Vieira + 210945: "CFF0", // Cindy Friedman + 210928: "BRF0", // Barry Finegold + 210931: "BPC0", // Brendan Crighton + 210924: "AHP1", // Alice Peisch + 210964: "FAM1" // Frank Moran } const VideoWrapper = styled.div` From 0edda019db8aa4996837f42d0ac350438966acda Mon Sep 17 00:00:00 2001 From: Mephistic Date: Mon, 14 Sep 2026 10:59:47 -0400 Subject: [PATCH 5/6] Add simple browse page to select between currently available test hearings - still needs an actual design, but this gets the information out there --- pages/hearings/browse.tsx | 87 ++++++++++++++++++++++++++++++++++ public/data/committees.json | 1 + public/data/hearings.json | 1 + public/data/people.json | 1 + public/locales/en/hearing.json | 5 ++ 5 files changed, 95 insertions(+) create mode 100644 pages/hearings/browse.tsx create mode 100644 public/data/committees.json create mode 100644 public/data/hearings.json create mode 100644 public/data/people.json diff --git a/pages/hearings/browse.tsx b/pages/hearings/browse.tsx new file mode 100644 index 000000000..6896d6a70 --- /dev/null +++ b/pages/hearings/browse.tsx @@ -0,0 +1,87 @@ +import { GetStaticProps } from "next" +import Link from "next/link" +import { useTranslation } from "next-i18next" +import { serverSideTranslations } from "next-i18next/serverSideTranslations" +import { Container, Table } from "components/bootstrap" +import { createPage } from "components/page" +import hearingsData from "public/data/hearings.json" + +type Hearing = { + hid: number + title: string + date: string + chamber: string + type: string + bills_discussed: string | null +} + +const hearings = hearingsData.data.hearings as Hearing[] + +// bills_discussed lists one bill per line, using inconsistent \n / \r\n separators +const splitBillsDiscussed = (billsDiscussed: string | null) => + billsDiscussed + ?.split(/\r?\n/) + .map(line => line.trim()) + .filter(Boolean) ?? [] + +const BrowseHearingsPage = createPage({ + titleI18nKey: "navigation.browseHearings", + Page: () => { + const { t } = useTranslation("hearing") + + return ( + +

{t("navigation.browseHearings", { ns: "common" })}

+ + + + + + + + + + + + {hearings.map(hearing => ( + + + + + + + + ))} + +
{t("title")}{t("date")}{t("chamber")}{t("type")}{t("bills_discussed")}
+ + {hearing.title} + + {hearing.date}{hearing.chamber}{hearing.type} + {splitBillsDiscussed(hearing.bills_discussed).map( + (line, i) => ( +
{line}
+ ) + )} +
+
+ ) + } +}) + +export default BrowseHearingsPage + +export const getStaticProps: GetStaticProps = async ctx => { + const locale = ctx.locale ?? ctx.defaultLocale ?? "en" + + return { + props: { + ...(await serverSideTranslations(locale, [ + "auth", + "common", + "footer", + "hearing" + ])) + } + } +} diff --git a/public/data/committees.json b/public/data/committees.json new file mode 100644 index 000000000..d52c23666 --- /dev/null +++ b/public/data/committees.json @@ -0,0 +1 @@ +{"data":{"committees":[{"chamber":"House","cid":1708,"last_modified":1781910678,"name":"Operations, Facilities and Security(H)","pids":[210876,210905,210924,210936,210954,210980,210981,210986,210993,211029,211056],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"House","cid":1709,"last_modified":1781910678,"name":"Federal Funding, Policy and Accountability (H)","pids":[210872,210874,210880,210887,210916,210990,211041,211046,211058,211061,211062],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Senate","cid":1710,"last_modified":1781910679,"name":"Ways and Means (S)","pids":[210870,210911,210912,210913,210914,210915,210931,210979,210998,211013,211014,211018,211021,211022,211028,211047,211064,211065],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Senate","cid":1711,"last_modified":1781910679,"name":"Ethics (S)","pids":[210931,210934,210939,210945,210971,211021,211032],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Senate","cid":1712,"last_modified":1781910679,"name":"Intergovernmental Affairs (S)","pids":[210869,210870,210871,210928,211011,211012],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1713,"last_modified":1781910679,"name":"Bonding, Capital Expenditures and State Assets","pids":[210871,210879,210885,210892,210898,210899,210911,210914,210976,210982,210985,211003,211006,211012,211019,211028,211058,211062,211065,211071],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Senate","cid":1714,"last_modified":1781910679,"name":"Steering and Policy (S)","pids":[210912,210934,210939,210945,210979,211044],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Senate","cid":1715,"last_modified":1781910679,"name":"Personnel and Administration (S)","pids":[210870,210931,210945,211014,211022,211032,211068],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Senate","cid":1716,"last_modified":1781910679,"name":"Bills in the Third Reading (S)","pids":[210934,211013,211018,211032,211044],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1717,"last_modified":1781910679,"name":"Racial Equity, Civil Rights, and Inclusion","pids":[210884,210906,210913,210915,210934,210935,210952,210962,210979,210987,211009,211029,211049,211060,211062,211064],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Senate","cid":1718,"last_modified":1781910679,"name":"Rules (S)","pids":[210931,210934,210945,210971,210973,211028,211044],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Senate","cid":1719,"last_modified":1781910685,"name":"Climate Change and Global Warming (S)","pids":[210939,210973,210979,210997,211021,211064],"session_year":"2025-2026","topic":["Climate","Change"],"type":"Standing"},{"chamber":"Senate","cid":1720,"last_modified":1781910679,"name":"Post Audit and Oversight (S)","pids":[210928,210931,210969,210979,211011,211018,211028,211068],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Senate","cid":1721,"last_modified":1781910679,"name":"Census (S)","pids":[210911,210915,210928,211011,211027,211028,211044],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Senate","cid":1722,"last_modified":1781910685,"name":"Juvenile and Emerging Adult Justice (S)","pids":[210912,210913,210915,210931,210939,211064,211068],"session_year":"2025-2026","topic":["Justice"],"type":"Standing"},{"chamber":"Joint","cid":1723,"last_modified":1781910680,"name":"Emergency Preparedness and Management","pids":[210871,210872,210881,210885,210891,210893,210948,210961,210973,210998,211028,211035,211046,211052,211061,211063,211064],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"House","cid":1724,"last_modified":1781910680,"name":"Intergovernmental Affairs","pids":[210875,210879,210881,210889,210898,210919,210925,210947,211002,211006,211020],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1725,"last_modified":1781910680,"name":"Ad Info Tech/Cybersecurity","pids":[210876,210880,210881,210891,210911,210912,210928,210967,210978,210997,211010,211012,211038,211039,211057,211060,211068],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1726,"last_modified":1781910680,"name":"Tourism, Arts and Cultural Development (J)","pids":[210879,210880,210911,210929,210930,210934,210956,210961,210962,210997,211006,211009,211027,211033,211052,211057,211064],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1727,"last_modified":1781910680,"name":"Municipalities and Regional Government (J)","pids":[210873,210877,210888,210890,210909,210917,210942,210966,210983,210996,211006,211012,211014,211019,211027,211052,211068],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1728,"last_modified":1781910685,"name":"Telecommunications, Utilities and Energy (J)","pids":[210869,210883,210910,210932,210934,210944,210958,210987,210991,210997,210998,210999,211016,211046,211055,211065,211067],"session_year":"2025-2026","topic":["Technology"],"type":"Standing"},{"chamber":"Joint","cid":1729,"last_modified":1781910685,"name":"Higher Education (J)","pids":[210870,210872,210878,210890,210900,210911,210912,210942,210959,210978,210979,211004,211012,211036,211052,211058],"session_year":"2025-2026","topic":["Education"],"type":"Standing"},{"chamber":"House","cid":1730,"last_modified":1781910680,"name":"Climate Action and Sustainability (H)","pids":[210874,210876,210885,210887,210888,210889,210891,210898,210947,211005,211040],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1731,"last_modified":1781910680,"name":"Special Joint Committee on Initiative Petitions","pids":[210924,210928,210931,210945,210961,210964,210993,211000,211022,211028],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1732,"last_modified":1781910681,"name":"Veterans and Federal Affairs (J)","pids":[210876,210888,210889,210893,210900,210902,210926,210975,210982,210998,211011,211014,211018,211020,211028,211046,211050],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"House","cid":1733,"last_modified":1781910681,"name":"Human Resources and Employee Engagement(H)","pids":[210882,210886,210895,210933,210936,210974,211004,211010,211017,211050,211051,211054,211059],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1734,"last_modified":1781910685,"name":"Housing (J)","pids":[210872,210896,210902,210928,210946,210949,210950,210952,210987,211021,211022,211030,211044,211047,211048,211049,211070],"session_year":"2025-2026","topic":["Housing"],"type":"Standing"},{"chamber":"House","cid":1735,"last_modified":1781910681,"name":"Ethics (H)","pids":[210924,210936,210958,210961,210965,210989,210992,210993,211000,211019,211034],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"House","cid":1736,"last_modified":1781910681,"name":"Steering, Policy and Scheduling (H)","pids":[210875,210883,210899,210907,210929,210943,210949,210965,210994,211002,211034],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1737,"last_modified":1781910681,"name":"State Administration and Regulatory Oversight (J)","pids":[210873,210874,210875,210893,210895,210918,210941,210942,210944,210965,210969,210982,211018,211027,211032,211068,211070],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1738,"last_modified":1781910685,"name":"Public Health (J)","pids":[210870,210871,210883,210884,210889,210900,210901,210909,210913,210930,210965,210971,210983,210987,211001,211005,211053],"session_year":"2025-2026","topic":["Health"],"type":"Standing"},{"chamber":"Joint","cid":1739,"last_modified":1781910685,"name":"Transportation (J)","pids":[210869,210895,210911,210931,210943,210952,210956,210967,210968,210971,210996,211019,211021,211044,211047,211057,211059,211060,211069,211070],"session_year":"2025-2026","topic":["Transportation"],"type":"Standing"},{"chamber":"Joint","cid":1740,"last_modified":1781910682,"name":"Judiciary (J)","pids":[210880,210896,210903,210906,210915,210919,210941,210950,210969,210982,211000,211016,211021,211025,211047,211054,211056],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1741,"last_modified":1781910682,"name":"Children, Families and Persons with Disabilities (J)","pids":[210880,210899,210908,210913,210915,210916,210919,210947,210949,210969,210972,211002,211021,211027,211047,211069,211071],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"House","cid":1742,"last_modified":1781910682,"name":"Post Audit and Oversight (H)","pids":[210881,210896,210905,210954,210974,210976,210980,210985,210986,211053,211061],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1743,"last_modified":1781910682,"name":"Public Service (J)","pids":[210870,210888,210902,210904,210914,210926,210941,210952,210958,210960,210969,210983,210998,211011,211016,211041,211066],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"House","cid":1744,"last_modified":1781910682,"name":"Rules (H)","pids":[210924,210936,210940,210954,210957,210962,210964,210993,210999,211008,211023,211024,211045,211048],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1745,"last_modified":1781910682,"name":"Rules (J)","pids":[210924,210931,210934,210936,210940,210945,210954,210957,210962,210964,210971,210973,210993,210999,211008,211023,211024,211028,211044,211045,211048],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1746,"last_modified":1781910682,"name":"Public Safety and Homeland Security (J)","pids":[210869,210871,210877,210882,210884,210886,210890,210904,210905,210907,210926,210951,210956,210969,210982,211005,211012,211063,211065,211068],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"House","cid":1747,"last_modified":1781910682,"name":"Bills in the Third Reading (H)","pids":[210929,210991,211043],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1748,"last_modified":1781910685,"name":"Health Care Financing (J)","pids":[210870,210871,210892,210908,210912,210944,210945,210946,210957,210965,210970,210987,210996,211022,211024,211039,211049,211054,211065,211066],"session_year":"2025-2026","topic":["Health"],"type":"Standing"},{"chamber":"Joint","cid":1749,"last_modified":1781910683,"name":"Financial Services (J)","pids":[210871,210873,210897,210903,210907,210914,210934,210948,210977,210989,211012,211022,211034,211040,211053,211064,211067],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1750,"last_modified":1781910683,"name":"Community Development and Small Businesses (J)","pids":[210870,210873,210878,210889,210916,210923,210929,210943,210973,210983,210985,210988,210998,211018,211020,211064],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1751,"last_modified":1781910685,"name":"Mental Health, Substance Use and Recovery (J)","pids":[210870,210883,210913,210916,210939,210941,210946,210957,210982,210983,210987,211002,211007,211009,211018,211029,211034,211036,211063,211066],"session_year":"2025-2026","topic":["Health"],"type":"Standing"},{"chamber":"Joint","cid":1752,"last_modified":1781910683,"name":"Revenue (J)","pids":[210877,210882,210890,210898,210917,210920,210956,210969,210983,210998,211010,211017,211023,211025,211027,211028,211059],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1753,"last_modified":1781910685,"name":"Economic Development and Emerging Technologies (J)","pids":[210885,210886,210894,210904,210905,210911,210915,210928,210940,210943,210988,211004,211018,211022,211051,211055,211061,211065,211067,211068],"session_year":"2025-2026","topic":["Economy"],"type":"Standing"},{"chamber":"Joint","cid":1754,"last_modified":1781910683,"name":"Consumer Protection and Professional Licensure (J)","pids":[210870,210871,210884,210893,210912,210914,210949,210950,210967,210976,210978,211009,211037,211039,211047,211065,211071],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1755,"last_modified":1781910683,"name":"Election Laws (J)","pids":[210874,210878,210897,210901,210906,210914,210939,210946,210955,210958,210969,210978,210983,211010,211024,211027,211028],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1756,"last_modified":1781910684,"name":"Labor and Workforce Development (J)","pids":[210875,210886,210887,210896,210897,210914,210930,210962,210971,211021,211022,211025,211026,211032,211039,211048,211070],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1757,"last_modified":1781910685,"name":"Environment and Natural Resources (J)","pids":[210869,210876,210878,210886,210887,210892,210895,210903,210910,210917,210934,210938,210988,211012,211014,211027,211052],"session_year":"2025-2026","topic":["Environment"],"type":"Standing"},{"chamber":"Joint","cid":1758,"last_modified":1781910685,"name":"Education (J)","pids":[210882,210894,210901,210903,210907,210908,210912,210913,210919,210930,210971,210992,211021,211025,211032,211055,211069],"session_year":"2025-2026","topic":["Education"],"type":"Standing"},{"chamber":"Joint","cid":1759,"last_modified":1781910684,"name":"Ways and Means (J)","pids":[210870,210873,210894,210897,210900,210901,210904,210905,210906,210908,210909,210910,210911,210912,210913,210914,210915,210917,210919,210922,210926,210931,210944,210948,210967,210976,210979,210996,210998,211013,211014,211016,211018,211020,211021,211022,211028,211029,211041,211047,211049,211050,211053,211054,211057,211058,211060,211063,211064,211065,211066,211069],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"House","cid":1760,"last_modified":1781910684,"name":"Ways and Means (H)","pids":[210873,210894,210897,210900,210901,210904,210905,210906,210908,210909,210910,210917,210919,210922,210926,210944,210948,210967,210976,210996,211016,211020,211029,211041,211049,211050,211053,211054,211057,211058,211060,211063,211066,211069],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1761,"last_modified":1781910685,"name":"Cannabis Policy (J)","pids":[210869,210882,210885,210892,210894,210950,210953,210969,210983,211004,211025,211050,211051,211056,211064,211067,211068],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Senate","cid":1762,"last_modified":1781910685,"name":"Subcommittee on Rules","pids":[210945,210979,211022,211044],"session_year":"2025-2026","topic":[],"type":"Standing"},{"chamber":"Joint","cid":1763,"last_modified":1781910685,"name":"Agriculture and Fisheries","pids":[210869,210877,210879,210881,210891,210899,210902,210913,210914,210947,210973,210979,210988,210991,211017,211028],"session_year":"2025-2026","topic":["Agriculture"],"type":"Standing"},{"chamber":"Joint","cid":1764,"last_modified":1781910685,"name":"Aging and Independence","pids":[210909,210910,210942,210945,210948,210952,210973,210982,211005,211014,211017,211025,211036,211042,211062,211068,211071],"session_year":"2025-2026","topic":[],"type":"Standing"}]},"page":1,"per_page":100,"total_pages":1,"total_results":57} \ No newline at end of file diff --git a/public/data/hearings.json b/public/data/hearings.json new file mode 100644 index 000000000..89759d131 --- /dev/null +++ b/public/data/hearings.json @@ -0,0 +1 @@ +{"data":{"hearings":[{"bids":["MA_20250H5004"],"bills_discussed":"H 5004 - An Act to improve access to public records","chamber":"Joint","cids":[1731],"date":"2026-03-03","hid":279802,"last_modified":1788991941,"pids":[210945,210924,213848,213849,211022,211028,210993,210415,210928,211000,213858,213851,210961,213857,213874],"session_year":"2025-2026","title":"Special Joint Committee on Initiative Petitions","topic":null,"type":"Regular"},{"bids":["MA_20250H5009","MA_20250H5000"],"bills_discussed":"H 5000 - An Act to allow single-family homes on small lots in areas with adequate infrastructure\nH 5009 - An Act relative to Labor Relations Policies for Committee for Public Counsel Services Employees \r\n","chamber":"Joint","cids":[1731],"date":"2026-03-16","hid":279803,"last_modified":1788991941,"pids":[211000,211022,213639,213640,213641,213642,210961,213698,213699,213700,210993,213643,213877,210928,210931,210945,210964,210924,213880,213881,213882,213883,213884,213885,211028,213896,213895,213897,213898],"session_year":"2025-2026","title":"Special Joint Committee on Initiative Petitions","topic":null,"type":"Regular"},{"bids":["MA_20250H5010","MA_20250H5008"],"bills_discussed":"H 5008 - An Act to Protect Tenants by Limiting Rent Increases\r\n\nH 5010 - An Act to Reform and Regulate Legislative Stipends \r\n\r\n","chamber":"Joint","cids":[1731],"date":"2026-03-17","hid":279804,"last_modified":1788991941,"pids":[210924,210945,213944,213945,213643,213946,213947,213951,213952,213953,210931,211028,211022,211000,210964,213962,213965,210961,213966,213967,213857,213968,213969,213971,213972,213973,213899,213900,213901,213902,213905,213908,210928,213916,213917,213918,213919,213920,210427,213923,213933,210405,213932,213934,213931,213930,213936,213937,213938,213939,210541,213940,213941],"session_year":"2025-2026","title":"Special Joint Committee on Initiative Petitions","topic":null,"type":"Regular"},{"bids":["MA_20250H5001","MA_20250H5003"],"bills_discussed":"H 5001 - An Act relative to election day registration\nH 5003 - An Act to implement all-party state primaries","chamber":"Joint","cids":[1731],"date":"2026-03-31","hid":279805,"last_modified":1789190251,"pids":[210924,213823,210928,213824,213825,211000,211028,210961,211045,213838,213839,213840,213841,210993,213842,213843,213844,213845,213846,213847,214019,213952,214020,214021,210945,214008,214007,214009,214010,214011,213643,211022,210964,214013,214014,214015,214018],"session_year":"2025-2026","title":"Special Joint Committee on Initiative Petitions","topic":null,"type":"Regular"},{"bids":["MA_20250H5007","MA_20250H5006"],"bills_discussed":"H 5007 - An Act relative to Reducing the State Personal Income Tax Rate from 5% To 4%\r\n\nH 5006 - An Act relative to limiting state tax collection growth and returning surpluses to taxpayers","chamber":"Joint","cids":[1731],"date":"2026-03-30","hid":279806,"last_modified":1789190251,"pids":[210945,210924,213794,211000,210928,211028,210931,213800,213801,213802,213803,211022,210961,210964,213805,213806,213807,213808,213811,213812,213813,210414,213814,213815,213816,210415,213817,213818,213819],"session_year":"2025-2026","title":"Special Joint Committee on Initiative Petitions","topic":null,"type":"Regular"},{"bids":["MA_20250H5005","MA_20250H5002"],"bills_discussed":"H 5005 - An Act to protect water and nature\nH 5002 - An Act to restore a sensible marijuana policy","chamber":"Joint","cids":[1731],"date":"2026-03-23","hid":279807,"last_modified":1788991941,"pids":[210924,210931,213716,210945,213718,213726,213730,213737,213742,213747,210928,210993,210961,211000,213782,213783,213784,213785,213786,213787,213989,213990,211022,210964,213993,213994,213996,213997,213998,213999],"session_year":"2025-2026","title":"Special Joint Committee on Initiative Petitions","topic":null,"type":"Regular"}]},"page":1,"per_page":10,"total_pages":1,"total_results":6} \ No newline at end of file diff --git a/public/data/people.json b/public/data/people.json new file mode 100644 index 000000000..ad58045bd --- /dev/null +++ b/public/data/people.json @@ -0,0 +1 @@ +{"data":{"people":[{"first":"Dylan","image":null,"last":"Fernandes","last_modified":1789376456,"pid":210869,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Kelly","image":null,"last":"Dooner","last_modified":1789376456,"pid":210870,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"William","image":null,"last":"Driscoll","last_modified":1789376456,"pid":210871,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Michelle","image":null,"last":"Badger","last_modified":1789376456,"pid":210872,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Michael","image":null,"last":"Chaisson","last_modified":1789376456,"pid":210873,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Leigh","image":null,"last":"Davis","last_modified":1789376456,"pid":210874,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Dennis","image":null,"last":"Gallagher","last_modified":1789376456,"pid":210875,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"John","image":null,"last":"Gaskey","last_modified":1789376456,"pid":210876,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Homar","image":null,"last":"Gómez","last_modified":1789376456,"pid":210877,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Tara","image":null,"last":"Hong","last_modified":1789376456,"pid":210878,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Hadley","image":null,"last":"Luddy","last_modified":1789376456,"pid":210879,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Thomas","image":null,"last":"Moakley","last_modified":1789376456,"pid":210880,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Steven","image":null,"last":"Ouellette","last_modified":1789376456,"pid":210881,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Bridget","image":null,"last":"Plouffe","last_modified":1789376456,"pid":210882,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Sean","image":null,"last":"Reid","last_modified":1789376456,"pid":210883,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Amy","image":null,"last":"Sangiolo","last_modified":1789376456,"pid":210884,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Greg","image":null,"last":"Schwartz","last_modified":1789376456,"pid":210885,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Kenneth","image":null,"last":"Sweezey","last_modified":1789376456,"pid":210886,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Mark","image":null,"last":"Sylvia","last_modified":1789376456,"pid":210887,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Joshua","image":null,"last":"Tarsky","last_modified":1789376456,"pid":210888,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Justin","image":null,"last":"Thurber","last_modified":1789376456,"pid":210889,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Richard","image":null,"last":"Wells","last_modified":1789376456,"pid":210890,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Christopher","image":null,"last":"Flanagan","last_modified":1789376456,"pid":210891,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Dawne","image":null,"last":"Shand","last_modified":1789376456,"pid":210892,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Estela","image":null,"last":"Reyes","last_modified":1789376456,"pid":210893,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Manny","image":null,"last":"Cruz","last_modified":1789376456,"pid":210894,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Jennifer","image":null,"last":"Armini","last_modified":1789376456,"pid":210895,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Adrianne","image":null,"last":"Ramos","last_modified":1789376456,"pid":210896,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Ryan","image":null,"last":"Hamilton","last_modified":1789376456,"pid":210897,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Francisco","image":null,"last":"Paulino","last_modified":1789376456,"pid":210898,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Aaron","image":null,"last":"Saunders","last_modified":1789376456,"pid":210899,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Shirley","image":null,"last":"Arriaga","last_modified":1789376456,"pid":210900,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Priscila","image":null,"last":"Sousa","last_modified":1789376456,"pid":210901,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"James","image":null,"last":"Arena-DeRosa","last_modified":1789376456,"pid":210902,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Simon","image":null,"last":"Cataldo","last_modified":1789376456,"pid":210903,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2011-2012","2013-2014","2023-2024","2025-2026"]}]},{"first":"Rodney","image":null,"last":"Elliott","last_modified":1789376456,"pid":210904,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Marcus","image":null,"last":"Vaughn","last_modified":1789376456,"pid":210905,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Rita","image":null,"last":"Mendes","last_modified":1789376456,"pid":210906,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Christopher","image":null,"last":"Worrell","last_modified":1789376456,"pid":210907,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2023-2024","2025-2026"]}]},{"first":"Judith","image":null,"last":"Garcia","last_modified":1789376456,"pid":210908,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Samantha","image":null,"last":"Montaño","last_modified":1789376456,"pid":210909,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Margaret","image":null,"last":"Scarsdale","last_modified":1789376456,"pid":210910,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Paul","image":null,"last":"Mark","last_modified":1789376456,"pid":210911,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Pavel","image":null,"last":"Payano","last_modified":1789376456,"pid":210912,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Robyn","image":null,"last":"Kennedy","last_modified":1789376456,"pid":210913,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Jacob","image":null,"last":"Oliveira","last_modified":1789376456,"pid":210914,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Liz","image":null,"last":"Miranda","last_modified":1789376456,"pid":210915,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Kate","image":null,"last":"Donaghue","last_modified":1789376456,"pid":210916,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Kristin","image":null,"last":"Kassner","last_modified":1789376456,"pid":210917,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Antonio","image":null,"last":"Cabral","last_modified":1789376456,"pid":210918,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","1995-1996","1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Alyson","image":null,"last":"Sullivan-Almeida","last_modified":1789376456,"pid":210919,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","1995-1996","1997-1998","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Adrian","image":null,"last":"Madaro","last_modified":1789376456,"pid":210920,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Ann-Margaret","image":null,"last":"Ferrante","last_modified":1789376456,"pid":210921,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Aaron","image":null,"last":"Michlewitz","last_modified":1789376456,"pid":210922,"testimony_minutes":null,"type":[{"Legislator":["1995-1996","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Andres","image":null,"last":"Vargas","last_modified":1789376456,"pid":210923,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Alice","image":null,"last":"Peisch","last_modified":1789376456,"pid":210924,"testimony_minutes":null,"type":[{"Legislator":["2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Angelo","image":null,"last":"Puppolo","last_modified":1789376456,"pid":210925,"testimony_minutes":null,"type":[{"Legislator":["2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Alan","image":null,"last":"Silvia","last_modified":1789376456,"pid":210926,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Andrew","image":null,"last":"Tarr","last_modified":1789376456,"pid":210927,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Barry","image":null,"last":"Finegold","last_modified":1789376456,"pid":210928,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Brian","image":null,"last":"Ashe","last_modified":1789376456,"pid":210929,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Bruce","image":null,"last":"Ayers","last_modified":1789376456,"pid":210930,"testimony_minutes":null,"type":[{"Legislator":["1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Brendan","image":null,"last":"Crighton","last_modified":1789376456,"pid":210931,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Bradley","image":null,"last":"Jones","last_modified":1789376456,"pid":210932,"testimony_minutes":null,"type":[{"Legislator":["1995-1996","1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Brian","image":null,"last":"Murray","last_modified":1789376456,"pid":210933,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Bruce","image":null,"last":"Tarr","last_modified":1789376456,"pid":210934,"testimony_minutes":null,"type":[{"Legislator":["1995-1996","1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Bud","image":null,"last":"Williams","last_modified":1789376456,"pid":210935,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Carlos","image":null,"last":"González","last_modified":1789376456,"pid":210936,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Carol","image":null,"last":"Doherty","last_modified":1789376456,"pid":210937,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Christine","image":null,"last":"Barber","last_modified":1789376456,"pid":210938,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Cynthia","image":null,"last":"Creem","last_modified":1789376456,"pid":210939,"testimony_minutes":null,"type":[{"Legislator":["1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Carole","image":null,"last":"Fiola","last_modified":1789376456,"pid":210940,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Colleen","image":null,"last":"Garry","last_modified":1789376456,"pid":210941,"testimony_minutes":null,"type":[{"Legislator":["1995-1996","1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Carmine","image":null,"last":"Gentile","last_modified":1789376456,"pid":210942,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Christopher","image":null,"last":"Hendricks","last_modified":1789376456,"pid":210943,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Chynah","image":null,"last":"Tyler","last_modified":1789376456,"pid":210944,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Cindy","image":null,"last":"Friedman","last_modified":1789376456,"pid":210945,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Christopher","image":null,"last":"Markey","last_modified":1789376456,"pid":210946,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Danillo","image":null,"last":"Sena","last_modified":1789376456,"pid":210947,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"David","image":null,"last":"Biele","last_modified":1789376456,"pid":210948,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"David","image":null,"last":"LeBoeuf","last_modified":1789376456,"pid":210949,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Donald","image":null,"last":"Berthiaume","last_modified":1789376456,"pid":210950,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Daniel","image":null,"last":"Cahill","last_modified":1789376456,"pid":210951,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","1995-1996","1997-1998","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"David","image":null,"last":"DeCoste","last_modified":1789376456,"pid":210952,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Daniel","image":null,"last":"Donahue","last_modified":1789376456,"pid":210953,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Danielle","image":null,"last":"Gregoire","last_modified":1789376456,"pid":210954,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Daniel","image":null,"last":"Hunt","last_modified":1789376456,"pid":210955,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"David","image":null,"last":"Linsky","last_modified":1789376456,"pid":210956,"testimony_minutes":null,"type":[{"Legislator":["1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"David","image":null,"last":"Muradian","last_modified":1789376456,"pid":210957,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"David","image":null,"last":"Robertson","last_modified":1789376456,"pid":210958,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"David","image":null,"last":"Rogers","last_modified":1789376456,"pid":210959,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Daniel","image":null,"last":"Ryan","last_modified":1789376456,"pid":210960,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"David","image":null,"last":"Vieira","last_modified":1789376456,"pid":210961,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Donald","image":null,"last":"Wong","last_modified":1789376456,"pid":210962,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Edward","image":null,"last":"Kennedy","last_modified":1789376456,"pid":210963,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Frank","image":null,"last":"Moran","last_modified":1789376456,"pid":210964,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Hannah","image":null,"last":"Kane","last_modified":1789376456,"pid":210965,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Jack","image":null,"last":"Lewis","last_modified":1789376456,"pid":210966,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"James","image":null,"last":"Hawkins","last_modified":1789376456,"pid":210967,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"James","image":null,"last":"Arciero","last_modified":1789376456,"pid":210968,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"James","image":null,"last":"Eldridge","last_modified":1789376456,"pid":210969,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"John","image":null,"last":"Lawn","last_modified":1789376456,"pid":210970,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Jason","image":null,"last":"Lewis","last_modified":1789376456,"pid":210971,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Jay","image":null,"last":"Livingstone","last_modified":1789376456,"pid":210972,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Joan","image":null,"last":"Lovely","last_modified":1789376456,"pid":210973,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"John","image":null,"last":"Mahoney","last_modified":1789376456,"pid":210974,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Joseph","image":null,"last":"McGonagle","last_modified":1789376456,"pid":210975,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Joseph","image":null,"last":"McKenna","last_modified":1789376456,"pid":210976,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"James","image":null,"last":"Murphy","last_modified":1789376456,"pid":210977,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","1995-1996","1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Joan","image":null,"last":"Meschino","last_modified":1789376456,"pid":210978,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Joanne","image":null,"last":"Comerford","last_modified":1789376456,"pid":210979,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"James","image":null,"last":"O'Day","last_modified":1789376456,"pid":210980,"testimony_minutes":null,"type":[{"Legislator":["2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"John","image":null,"last":"Barrett","last_modified":1789376456,"pid":210981,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"John","image":null,"last":"Velis","last_modified":1789376456,"pid":210982,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"John","image":null,"last":"Keenan","last_modified":1789376456,"pid":210983,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Jerald","image":null,"last":"Parisella","last_modified":1789376456,"pid":210984,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"John","image":null,"last":"Rogers","last_modified":1789376456,"pid":210985,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","1995-1996","1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Jeffrey","image":null,"last":"Roy","last_modified":1789376456,"pid":210986,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Julian","image":null,"last":"Cyr","last_modified":1789376456,"pid":210987,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Jonathan","image":null,"last":"Zlotnik","last_modified":1789376456,"pid":210988,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Kate","image":null,"last":"Lipper-Garabedian","last_modified":1789376456,"pid":210989,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Kathleen","image":null,"last":"LaNatra","last_modified":1789376456,"pid":210990,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Kimberly","image":null,"last":"Ferguson","last_modified":1789376456,"pid":210991,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Kenneth","image":null,"last":"Gordon","last_modified":1789376456,"pid":210992,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Kate","image":null,"last":"Hogan","last_modified":1789376456,"pid":210993,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Kevin","image":null,"last":"Honan","last_modified":1789376456,"pid":210994,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","1995-1996","1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Karen","image":null,"last":"Spilka","last_modified":1789376456,"pid":210995,"testimony_minutes":null,"type":[{"Legislator":["2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Lindsay","image":null,"last":"Sabadosa","last_modified":1789376456,"pid":210996,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Michael","image":null,"last":"Barrett","last_modified":1789376456,"pid":210997,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Michael","image":null,"last":"Brady","last_modified":1789376456,"pid":210998,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Mark","image":null,"last":"Cusack","last_modified":1789376456,"pid":210999,"testimony_minutes":null,"type":[{"Legislator":["1999-2000","2001-2002","2003-2004","2005-2006","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Michael","image":null,"last":"Day","last_modified":1789376456,"pid":211000,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Marjorie","image":null,"last":"Decker","last_modified":1789376456,"pid":211001,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Michelle","image":null,"last":"DuBois","last_modified":1789376456,"pid":211002,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Michael","image":null,"last":"Finn","last_modified":1789376456,"pid":211003,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Michael","image":null,"last":"Soter","last_modified":1789376456,"pid":211004,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Michelle","image":null,"last":"Ciccolo","last_modified":1789376456,"pid":211005,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Mike","image":null,"last":"Connolly","last_modified":1789376456,"pid":211006,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Mindy","image":null,"last":"Domb","last_modified":1789376456,"pid":211007,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Michael","image":null,"last":"Moran","last_modified":1789376456,"pid":211008,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","1995-1996","1997-1998","1999-2000","2001-2002","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Mary","image":null,"last":"Keefe","last_modified":1789376456,"pid":211009,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Marc","image":null,"last":"Lombardo","last_modified":1789376456,"pid":211010,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Mark","image":null,"last":"Montigny","last_modified":1789376456,"pid":211011,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","1995-1996","1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Michael","image":null,"last":"Moore","last_modified":1789376456,"pid":211012,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Michael","image":null,"last":"Rodrigues","last_modified":1789376456,"pid":211013,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Michael","image":null,"last":"Rush","last_modified":1789376456,"pid":211014,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Natalie","image":null,"last":"Blais","last_modified":1789376456,"pid":211015,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Natalie","image":null,"last":"Higgins","last_modified":1789376456,"pid":211016,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Nicholas","image":null,"last":"Boldyga","last_modified":1789376456,"pid":211017,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Nick","image":null,"last":"Collins","last_modified":1789376456,"pid":211018,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Norman","image":null,"last":"Orrall","last_modified":1789376456,"pid":211019,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Patrick","image":null,"last":"Kearney","last_modified":1789376456,"pid":211020,"testimony_minutes":null,"type":[{"Legislator":["1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Patrick","image":null,"last":"O'Connor","last_modified":1789376456,"pid":211021,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Paul","image":null,"last":"Feeney","last_modified":1789376456,"pid":211022,"testimony_minutes":null,"type":[{"Legislator":["2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Paul","image":null,"last":"Donato","last_modified":1789376456,"pid":211023,"testimony_minutes":null,"type":[{"Legislator":["2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Paul","image":null,"last":"Frost","last_modified":1789376456,"pid":211024,"testimony_minutes":null,"type":[{"Legislator":["1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Patricia","image":null,"last":"Jehlen","last_modified":1789376456,"pid":211025,"testimony_minutes":null,"type":[{"Legislator":["2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Paul","image":null,"last":"McMurtry","last_modified":1789376456,"pid":211026,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Rebecca","image":null,"last":"Rausch","last_modified":1789376456,"pid":211027,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Ryan","image":null,"last":"Fattman","last_modified":1789376456,"pid":211028,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Russell","image":null,"last":"Holmes","last_modified":1789376456,"pid":211029,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Richard","image":null,"last":"Haggerty","last_modified":1789376456,"pid":211030,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Ronald","image":null,"last":"Mariano","last_modified":1789376456,"pid":211031,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Sal","image":null,"last":"DiDomenico","last_modified":1789376456,"pid":211032,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Sean","image":null,"last":"Garballey","last_modified":1789376456,"pid":211033,"testimony_minutes":null,"type":[{"Legislator":["2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Steven","image":null,"last":"Howitt","last_modified":1789376456,"pid":211034,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Steven","image":null,"last":"Ultrino","last_modified":1789376456,"pid":211035,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Susannah","image":null,"last":"Whipps","last_modified":1789376456,"pid":211036,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Tackey","image":null,"last":"Chan","last_modified":1789376456,"pid":211037,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Tricia","image":null,"last":"Farley-Bouvier","last_modified":1789376456,"pid":211038,"testimony_minutes":null,"type":[{"Legislator":["2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Tommy","image":null,"last":"Vitolo","last_modified":1789376456,"pid":211039,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Tram","image":null,"last":"Nguyen","last_modified":1789376456,"pid":211040,"testimony_minutes":null,"type":[{"Legislator":["2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Todd","image":null,"last":"Smola","last_modified":1789376456,"pid":211041,"testimony_minutes":null,"type":[{"Legislator":["2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Thomas","image":null,"last":"Stanley","last_modified":1789376456,"pid":211042,"testimony_minutes":null,"type":[{"Legislator":["2001-2002","2003-2004","2005-2006","2007-2008","2009-2010","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Thomas","image":null,"last":"Walsh","last_modified":1789376456,"pid":211043,"testimony_minutes":null,"type":[{"Legislator":["2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"William","image":null,"last":"Brownsberger","last_modified":1789376456,"pid":211044,"testimony_minutes":null,"type":[{"Legislator":["2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"William","image":null,"last":"Galvin","last_modified":1789376456,"pid":211045,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","1995-1996","1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2011-2012","2013-2014","2015-2016","2017-2018","2019-2020","2021-2022","2023-2024","2025-2026"]}]},{"first":"Jeffrey","image":null,"last":"Turco","last_modified":1789376456,"pid":211046,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Lydia","image":null,"last":"Edwards","last_modified":1789376456,"pid":211047,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Rob","image":null,"last":"Consalvo","last_modified":1789376456,"pid":211048,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Kip","image":null,"last":"Diggs","last_modified":1789376456,"pid":211049,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Patricia","image":null,"last":"Duffy","last_modified":1789376456,"pid":211050,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Jessica","image":null,"last":"Giannino","last_modified":1789376456,"pid":211051,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Vanna","image":null,"last":"Howard","last_modified":1789376456,"pid":211052,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Sally","image":null,"last":"Kerans","last_modified":1789376456,"pid":211053,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","1995-1996","1997-1998","1999-2000","2001-2002","2003-2004","2021-2022","2023-2024","2025-2026"]}]},{"first":"Meghan","image":null,"last":"Kilcoyne","last_modified":1789376456,"pid":211054,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Michael","image":null,"last":"Kushmerek","last_modified":1789376456,"pid":211055,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Brandy","image":null,"last":"Fluker-Reid","last_modified":1789376456,"pid":211056,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Steven","image":null,"last":"Owens","last_modified":1789376456,"pid":211057,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Kelly","image":null,"last":"Pease","last_modified":1789376456,"pid":211058,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Edward","image":null,"last":"Philips","last_modified":1789376456,"pid":211059,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Orlando","image":null,"last":"Ramos","last_modified":1789376456,"pid":211060,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Adam","image":null,"last":"Scanlon","last_modified":1789376456,"pid":211061,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Erika","image":null,"last":"Uyterhoeven","last_modified":1789376456,"pid":211062,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Steven","image":null,"last":"Xiarhos","last_modified":1789376456,"pid":211063,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"Adam","image":null,"last":"Gómez","last_modified":1789376456,"pid":211064,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"John","image":null,"last":"Cronin","last_modified":1789376456,"pid":211065,"testimony_minutes":null,"type":[{"Legislator":["2021-2022","2023-2024","2025-2026"]}]},{"first":"John","image":null,"last":"Moran","last_modified":1789376456,"pid":211066,"testimony_minutes":null,"type":[{"Legislator":["1995-1996","1997-1998","1999-2000","2001-2002","2023-2024","2025-2026"]}]},{"first":"William","image":null,"last":"MacGregor","last_modified":1789376456,"pid":211067,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"Peter","image":null,"last":"Durant","last_modified":1789376456,"pid":211068,"testimony_minutes":null,"type":[{"Legislator":["2023-2024","2025-2026"]}]},{"first":"John","image":null,"last":"Marsi","last_modified":1789376456,"pid":211069,"testimony_minutes":null,"type":[{"Legislator":["1993-1994","1995-1996","1997-1998","1999-2000","2001-2002","2003-2004","2005-2006","2007-2008","2023-2024","2025-2026"]}]},{"first":"Hannah","image":null,"last":"Bowen","last_modified":1789376456,"pid":211070,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Lisa","image":null,"last":"Field","last_modified":1789376456,"pid":211071,"testimony_minutes":null,"type":[{"Legislator":["2025-2026"]}]},{"first":"Landon","image":null,"last":"Jacquinot","last_modified":1783501244,"pid":213639,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Philip","image":null,"last":"Roberts","last_modified":1783501244,"pid":213640,"testimony_minutes":null,"type":[{"State Agency Representative":["2025-2026"]}]},{"first":"Marjorie","image":null,"last":"Whitner","last_modified":1783501244,"pid":213641,"testimony_minutes":null,"type":[{"State Agency Representative":["2025-2026"]}]},{"first":"Anthony","image":null,"last":"Benedetti","last_modified":1783501244,"pid":213642,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Unidentified","image":null,"last":"Speaker","last_modified":1783501244,"pid":213643,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Tom","image":null,"last":"McKeever","last_modified":1783587644,"pid":213698,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Tanvi","image":null,"last":"Verma","last_modified":1783587644,"pid":213699,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"James","image":null,"last":"Vita","last_modified":1783587644,"pid":213700,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Stephanie","image":null,"last":"Cooper","last_modified":1783587644,"pid":213716,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"David","image":null,"last":"O'neil","last_modified":1783587644,"pid":213718,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Katie","image":null,"last":"Theoharides","last_modified":1783587644,"pid":213726,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Emma","image":null,"last":"Ellsworth","last_modified":1783587644,"pid":213730,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"David","image":null,"last":"McGlinchey","last_modified":1783587644,"pid":213737,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Andrew","image":null,"last":"Sharp","last_modified":1783587644,"pid":213742,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Abigail","image":null,"last":"McLean","last_modified":1783587644,"pid":213747,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Sam","image":null,"last":"Anderson","last_modified":1783587644,"pid":213782,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Catherine","image":null,"last":"Lang","last_modified":1783587644,"pid":213783,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Zachary","image":null,"last":"Sheldon","last_modified":1783587644,"pid":213784,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Laura","image":null,"last":"Jasinski","last_modified":1783587644,"pid":213785,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Anna","image":null,"last":"Darrow","last_modified":1783587644,"pid":213786,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Rob","image":null,"last":"Johnson","last_modified":1783587644,"pid":213787,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Doug","image":null,"last":"Howgate","last_modified":1783587644,"pid":213794,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Chris","image":null,"last":"Cohan","last_modified":1783587644,"pid":213800,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Christopher","image":null,"last":"Carlozzi","last_modified":1783587644,"pid":213801,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jim","image":null,"last":"Sturgis","last_modified":1783587644,"pid":213802,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Rebecca","image":null,"last":"Paxton","last_modified":1783587644,"pid":213803,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Bob","image":null,"last":"Rivers","last_modified":1783674043,"pid":213805,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jonathan","image":null,"last":"Gruber","last_modified":1783674043,"pid":213806,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Phineas","image":null,"last":"Baxandall","last_modified":1783674043,"pid":213807,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Max","image":null,"last":"Page","last_modified":1783674043,"pid":213808,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Margaret","image":null,"last":"Heights","last_modified":1783674043,"pid":213811,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Eden","image":null,"last":"Levari","last_modified":1783674043,"pid":213812,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Grace","image":null,"last":"Ross","last_modified":1783674043,"pid":213813,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jonathan","image":null,"last":"Cohen","last_modified":1783674043,"pid":213814,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Fred","image":null,"last":"Berman","last_modified":1783674043,"pid":213815,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Evan","image":null,"last":"Drukker-Schardl","last_modified":1783674043,"pid":213816,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Andrew","image":null,"last":"Fagan","last_modified":1783674043,"pid":213817,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Martha","image":null,"last":"Karchere","last_modified":1783674043,"pid":213818,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Cynthia","image":null,"last":"Yetman","last_modified":1783674043,"pid":213819,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Costas","image":null,"last":"Panagopoulos","last_modified":1783674043,"pid":213823,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Katie","image":null,"last":"King","last_modified":1783674043,"pid":213824,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Charles","image":null,"last":"Stewart","last_modified":1783674043,"pid":213825,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Norma","image":null,"last":"Shulman","last_modified":1783674043,"pid":213838,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Dave","image":null,"last":"Kaufman","last_modified":1783674043,"pid":213839,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Ali","image":null,"last":"Dibiteo","last_modified":1783674043,"pid":213840,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Ben","image":null,"last":"Kaufman","last_modified":1783674043,"pid":213841,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jeff","image":null,"last":"Cohen","last_modified":1783674043,"pid":213842,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jeff","image":null,"last":"Foster","last_modified":1783674043,"pid":213843,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Cheryl","image":null,"last":"Clyburn Crawford","last_modified":1783674043,"pid":213844,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Rahsaan","image":null,"last":"Hall","last_modified":1783674043,"pid":213845,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Celia","image":null,"last":"Canavan","last_modified":1783674043,"pid":213846,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"David","image":null,"last":"Green","last_modified":1783674043,"pid":213847,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"William","image":null,"last":"Clark","last_modified":1783674043,"pid":213848,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Rebecca","image":null,"last":"Murray","last_modified":1783674043,"pid":213849,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jesse","image":null,"last":"Littlewood","last_modified":1783674043,"pid":213851,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Scotia","image":null,"last":"Hilla","last_modified":1783760487,"pid":213857,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Diana","image":null,"last":"Dizoglio","last_modified":1783760487,"pid":213858,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Gerald","image":null,"last":"Duquette","last_modified":1783760487,"pid":213874,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Chris","image":null,"last":"Klutchman","last_modified":1783760487,"pid":213877,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Susan","image":null,"last":"Murphy","last_modified":1783760487,"pid":213880,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Andrew","image":null,"last":"Mikula","last_modified":1783760487,"pid":213881,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jesse","image":null,"last":"Kanson-Benanav","last_modified":1783760487,"pid":213882,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Max","image":null,"last":"Wolf","last_modified":1783760487,"pid":213883,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Sherry","image":null,"last":"Kasier","last_modified":1783760487,"pid":213884,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Deed","image":null,"last":"McCollum","last_modified":1783760487,"pid":213885,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Adam","image":null,"last":"Chaplain","last_modified":1783933241,"pid":213895,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Ali","image":null,"last":"Dimitayo","last_modified":1783933241,"pid":213896,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Dave","image":null,"last":"Kauffman","last_modified":1783933241,"pid":213897,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Ben","image":null,"last":"Fierro","last_modified":1783933241,"pid":213898,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Whitney","image":null,"last":"Airgood-Obrycki","last_modified":1783933241,"pid":213899,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Carolyn","image":null,"last":"Chu","last_modified":1783933241,"pid":213900,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Laura","image":null,"last":"Frost","last_modified":1783933241,"pid":213901,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Dave","image":null,"last":"Foley","last_modified":1783933241,"pid":213902,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Mark","image":null,"last":"Paul","last_modified":1783933241,"pid":213905,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Tram","image":null,"last":"Huang","last_modified":1783933241,"pid":213908,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Nandy","image":null,"last":"Soto","last_modified":1784019641,"pid":213916,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Tony","image":null,"last":"Lopes","last_modified":1784019641,"pid":213917,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Helen","image":null,"last":"Shiner","last_modified":1784019641,"pid":213918,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Michael","image":null,"last":"Monahan","last_modified":1784019641,"pid":213919,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Stefan","image":null,"last":"Ammenrah","last_modified":1784019641,"pid":213920,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"John","image":null,"last":"Gruber","last_modified":1784019641,"pid":213923,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Annie","image":null,"last":"Gordon","last_modified":1784019641,"pid":213930,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Annette","image":null,"last":"Diaz","last_modified":1784019641,"pid":213931,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Isaac","image":null,"last":"Hodes","last_modified":1784019641,"pid":213932,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jacqueline","image":null,"last":"Velez","last_modified":1784019641,"pid":213933,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Katie","image":null,"last":"McCann","last_modified":1784019641,"pid":213934,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Ace","image":null,"last":"Tayloe","last_modified":1784019641,"pid":213936,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Johnny","image":null,"last":"McInnis","last_modified":1784019641,"pid":213937,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Brent","image":null,"last":"Duncan","last_modified":1784019641,"pid":213938,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Robin","image":null,"last":"Tarosian","last_modified":1784019641,"pid":213939,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Shlomo","image":null,"last":"Pincus","last_modified":1784019641,"pid":213940,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Harry","image":null,"last":"Johnson","last_modified":1784019641,"pid":213941,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Emily","image":null,"last":"Ronco","last_modified":1784019641,"pid":213944,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Layla","image":null,"last":"Zaidane","last_modified":1784019641,"pid":213945,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jonathan","image":null,"last":"Hecht","last_modified":1784019645,"pid":213946,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Mary","image":null,"last":"Connington","last_modified":1784019645,"pid":213947,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Denise","image":null,"last":"Provost","last_modified":1784106042,"pid":213951,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Leonard","image":null,"last":"Mirra","last_modified":1784106042,"pid":213952,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jeanne","image":null,"last":"Kempthorne","last_modified":1784106042,"pid":213953,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Sean","image":null,"last":"Kealy","last_modified":1784106042,"pid":213962,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Thomas","image":null,"last":"Kiley","last_modified":1784106042,"pid":213965,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"John","image":null,"last":"Lippitt","last_modified":1784106042,"pid":213966,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Norman","image":null,"last":"Doust","last_modified":1784106042,"pid":213967,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Kathleen","image":null,"last":"Cavell","last_modified":1784106042,"pid":213968,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Barbara","image":null,"last":"Hansberry","last_modified":1784106042,"pid":213969,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Robert","image":null,"last":"Stifert","last_modified":1784106042,"pid":213971,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Anne","image":null,"last":"Ehlert","last_modified":1784106042,"pid":213972,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Amy","image":null,"last":"Carnevale","last_modified":1784106042,"pid":213973,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jessica","image":null,"last":"Troe","last_modified":1784192441,"pid":213989,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Wendy","image":null,"last":"Wakeman","last_modified":1784192441,"pid":213990,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Caroline","image":null,"last":"Pino","last_modified":1784192441,"pid":213993,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Kristen","image":null,"last":"Rogers","last_modified":1784192441,"pid":213994,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Judith","image":null,"last":"Ledbetter","last_modified":1784192441,"pid":213996,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Armani","image":null,"last":"White","last_modified":1784192441,"pid":213997,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Lucas","image":null,"last":"Thayer","last_modified":1784192441,"pid":213998,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jeff","image":null,"last":"Rawson","last_modified":1784192441,"pid":213999,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jim","image":null,"last":"Henderson","last_modified":1784192441,"pid":214007,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Danielle","image":null,"last":"Allen","last_modified":1784192441,"pid":214008,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Kevin","image":null,"last":"Johnson","last_modified":1784192441,"pid":214009,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Kate","image":null,"last":"Cavanagh","last_modified":1784192441,"pid":214010,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Spencer","image":null,"last":"Mortimer-Mills","last_modified":1784192441,"pid":214011,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Gina","image":null,"last":"Frank","last_modified":1784192445,"pid":214013,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Jordan","image":null,"last":"Berg Powers","last_modified":1784192445,"pid":214014,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Vanessa","image":null,"last":"Snow","last_modified":1784192445,"pid":214015,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Nathan","image":null,"last":"Lockwood","last_modified":1784278853,"pid":214018,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Evelyn","image":null,"last":"Doherty","last_modified":1784278853,"pid":214019,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"David","image":null,"last":"Green","last_modified":1784278853,"pid":214020,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]},{"first":"Bruce","image":null,"last":"Gordon","last_modified":1784278853,"pid":214021,"testimony_minutes":null,"type":[{"Advocate":["2025-2026"]}]}]},"page":1,"per_page":500,"total_pages":1,"total_results":331} \ No newline at end of file diff --git a/public/locales/en/hearing.json b/public/locales/en/hearing.json index 48f1c2087..8308f1b31 100644 --- a/public/locales/en/hearing.json +++ b/public/locales/en/hearing.json @@ -1,8 +1,11 @@ { "action": "Action", "bills_consideration": "Bills under consideration", + "bills_discussed": "Bills Discussed", "chairs": "Chairs", + "chamber": "Chamber", "committee_members": "Committee members", + "date": "Date", "download_transcript": "Download transcript", "download_transcript_x": "Download transcript for {{title}}", "hearing_details": "Hearing details", @@ -27,7 +30,9 @@ "see_all": "See all", "see_less": "See less", "senate_chair": "Senate Chair", + "title": "Title", "transcript_loading": "Loading transcript for this hearing...", + "type": "Type", "unknown_speaker": "Unknown speaker", "video_and_transcription_feature_callout": "Hearing Video + Transcription", "view_bill": "View Bill Details", From 3fe7ad889111ab2ee70f0e84f7419f5865f9c3fe Mon Sep 17 00:00:00 2001 From: Mephistic Date: Mon, 14 Sep 2026 16:51:57 -0400 Subject: [PATCH 6/6] Tweaks for demo hearing page --- components/hearing/DDHearingDetails.tsx | 207 ++++++++++++++++++++-- components/hearing/HearingSidebar.tsx | 18 +- components/hearing/digitalDemocracyApi.ts | 6 +- pages/hearings/browse.tsx | 4 +- public/locales/en/hearing.json | 1 + 5 files changed, 212 insertions(+), 24 deletions(-) diff --git a/components/hearing/DDHearingDetails.tsx b/components/hearing/DDHearingDetails.tsx index c9b4e1177..92780386a 100644 --- a/components/hearing/DDHearingDetails.tsx +++ b/components/hearing/DDHearingDetails.tsx @@ -1,9 +1,12 @@ +import { faMagnifyingGlass, faTimes } from "@fortawesome/free-solid-svg-icons" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" import { useTranslation } from "next-i18next" -import { useEffect, useState } from "react" +import { useEffect, useMemo, useRef, useState } from "react" import styled from "styled-components" -import { Carousel, Col, Container, Row } from "../bootstrap" +import { Badge, Carousel, Col, Container, Row } from "../bootstrap" import { Back } from "../shared/CommonComponents" import { Internal } from "../links" +import { formatMilliseconds } from "./hearing" import { HearingSidebar } from "./HearingSidebar" import { DDHearing, DDUtterance, speakerName } from "./digitalDemocracyApi" @@ -24,6 +27,11 @@ const ddApiPersonIdToMemberId: Record = { 210964: "FAM1" // Frank Moran } +const PARTY_ABBREVIATION: Record = { + Democrat: "D", + Republican: "R" +} + const VideoWrapper = styled.div` max-width: 700px; margin: 0 auto; @@ -46,6 +54,49 @@ const VideoChild = styled.video` border: none; ` +const SearchWrapper = styled.div` + position: relative; + width: 100%; + background-color: var(--maple-surface-hearing-search); + padding: 1rem; + margin-top: 1rem; + border-radius: 0.5rem; +` + +const SearchInput = styled.input` + width: 100%; + padding: 0.75rem 1rem; + border-radius: 0.5rem; + border: none; + background-color: var(--maple-surface-base); + font-size: 1rem; + outline: none; + color: var(--maple-brand-primary); + + &::placeholder { + color: var(--maple-text-muted); + } +` + +const SearchIcon = styled(FontAwesomeIcon)` + position: absolute; + right: 1.75rem; + top: 50%; + transform: translateY(-50%); + color: var(--maple-brand-primary); + font-size: 1rem; +` + +const ClearButton = styled(FontAwesomeIcon)` + position: absolute; + right: 3.5rem; + top: 50%; + transform: translateY(-50%); + color: var(--maple-brand-primary); + font-size: 1rem; + cursor: pointer; +` + const TranscriptContainer = styled(Container)` background-color: var(--maple-surface-base); max-height: 500px; @@ -53,22 +104,55 @@ const TranscriptContainer = styled(Container)` ` const TranscriptRow = styled(Row)` + cursor: pointer; + &:nth-child(even) { background-color: white; } &:nth-child(odd) { background-color: var(--maple-surface-transcript-stripe); } + &:hover { + background-color: var(--maple-surface-transcript-hover); + } ` const Speaker = styled.div` font-weight: 600; color: var(--maple-text-strong); + min-width: 160px; + max-width: 160px; ` +function csvField(value: string): string { + if (/["\n,]/.test(value)) return `"${value.replace(/"/g, '""')}"` + return value +} + +function utterancesToCsv(utterances: DDUtterance[]): string { + const header = ["Speaker", "Party", "Type", "Timestamp", "Text"] + const rows = utterances.map(utterance => { + const name = speakerName(utterance) ?? "Unknown speaker" + return [ + name, + utterance.party ?? "", + utterance.person_type, + formatMilliseconds(utterance.timestamp * 1000), + utterance.content + ] + .map(csvField) + .join(",") + }) + return [header.join(","), ...rows].join("\n") +} + export const DDHearingDetails = ({ hearing }: { hearing: DDHearing }) => { const { t } = useTranslation(["common", "hearing"]) const [utterances, setUtterances] = useState(null) + const [activeIndex, setActiveIndex] = useState(0) + const [searchTerm, setSearchTerm] = useState("") + const [downloadUrl, setDownloadUrl] = useState(null) + const videoRefs = useRef(new Map()) useEffect(() => { let cancelled = false @@ -83,10 +167,49 @@ export const DDHearingDetails = ({ hearing }: { hearing: DDHearing }) => { } }, [hearing.hid]) - const videos = [...hearing.hearing_videos].sort( - (a, b) => (a.start_time ?? a.uid) - (b.start_time ?? b.uid) + // Build a downloadable CSV of the full transcript entirely in the browser. + useEffect(() => { + if (!utterances || utterances.length === 0) { + setDownloadUrl(null) + return + } + const blob = new Blob([utterancesToCsv(utterances)], { + type: "text/csv;charset=utf-8;" + }) + const url = URL.createObjectURL(blob) + setDownloadUrl(url) + return () => { + URL.revokeObjectURL(url) + } + }, [utterances]) + + const videos = useMemo( + () => + [...hearing.hearing_videos].sort( + (a, b) => (a.start_time ?? a.uid) - (b.start_time ?? b.uid) + ), + [hearing.hearing_videos] ) + const filteredUtterances = useMemo(() => { + if (!utterances) return [] + if (!searchTerm) return utterances + return utterances.filter(utterance => + utterance.content.toLowerCase().includes(searchTerm.toLowerCase()) + ) + }, [utterances, searchTerm]) + + // `file_id` ties an utterance to a specific video; `timestamp` is an offset + // in seconds from the start of that video. + const handleSeek = (utterance: DDUtterance) => { + const index = videos.findIndex(video => video.file_id === utterance.file_id) + if (index === -1) return + const video = videoRefs.current.get(index) + if (!video) return + video.currentTime = utterance.timestamp + if (index !== activeIndex) setActiveIndex(index) + } + return ( @@ -105,12 +228,22 @@ export const DDHearingDetails = ({ hearing }: { hearing: DDHearing }) => { interval={null} indicators={videos.length > 1} controls={videos.length > 1} + activeIndex={activeIndex} + onSelect={index => setActiveIndex(index)} > - {videos.map(video => ( + {videos.map((video, index) => ( - + { + if (elem) videoRefs.current.set(index, elem) + else videoRefs.current.delete(index) + }} + src={video.video_url} + controls + muted + /> @@ -118,13 +251,30 @@ export const DDHearingDetails = ({ hearing }: { hearing: DDHearing }) => { ) : null} - + + setSearchTerm(e.target.value)} + /> + {searchTerm && ( + setSearchTerm("")} /> + )} + + + + {utterances === null ? (
{t("transcript_loading", { ns: "hearing" })}
+ ) : filteredUtterances.length === 0 && searchTerm ? ( +
+ {t("no_results_found", { ns: "hearing", searchTerm })} +
) : ( - utterances.map(utterance => { + filteredUtterances.map(utterance => { const name = speakerName(utterance) ?? t("unknown_speaker", { ns: "hearing" }) @@ -133,19 +283,36 @@ export const DDHearingDetails = ({ hearing }: { hearing: DDHearing }) => { utterance.pid !== null ? ddApiPersonIdToMemberId[utterance.pid] : undefined + const partyAbbreviation = utterance.party + ? PARTY_ABBREVIATION[utterance.party] + : undefined return ( - - - {memberId ? ( - - {name} - - ) : ( - name - )} - -
{utterance.content}
+ handleSeek(utterance)} + > + + + {memberId ? ( + + {name} + + ) : ( + name + )} + {partyAbbreviation && ` (${partyAbbreviation})`} + {utterance.person_type === "legislator" && ( +
+ + {t("legislator_tag", { ns: "hearing" })} + +
+ )} +
+
{utterance.content}
+
) }) @@ -158,6 +325,8 @@ export const DDHearingDetails = ({ hearing }: { hearing: DDHearing }) => { activeVideo={0} billsInAgenda={null} committeeCode={COMMITTEE_CODE} + externalDownloadFilename="transcript.csv" + externalDownloadUrl={downloadUrl ?? undefined} generalCourtNumber={GENERAL_COURT_NUMBER} hearingDate={hearing.date} transcripts={null} diff --git a/components/hearing/HearingSidebar.tsx b/components/hearing/HearingSidebar.tsx index 7978b5a13..9214560a4 100644 --- a/components/hearing/HearingSidebar.tsx +++ b/components/hearing/HearingSidebar.tsx @@ -123,6 +123,8 @@ export const HearingSidebar = ({ activeVideo, billsInAgenda, committeeCode, + externalDownloadFilename, + externalDownloadUrl, generalCourtNumber, hearingDate, transcripts @@ -130,6 +132,9 @@ export const HearingSidebar = ({ activeVideo: number billsInAgenda: any[] | null committeeCode: string | null + // Used when the download link is built client-side rather than from `transcripts`. + externalDownloadFilename?: string + externalDownloadUrl?: string generalCourtNumber: string | null hearingDate: string | null transcripts: (TranscriptData | null)[] | null @@ -218,7 +223,7 @@ export const HearingSidebar = ({ {t("hearing_details", { ns: "hearing" })} - {dateCheck || downloadURL !== "" ? ( + {dateCheck || downloadURL !== "" || externalDownloadUrl ? ( {dateCheck ? ( <> @@ -250,6 +255,17 @@ export const HearingSidebar = ({ ) : ( <> )} + {externalDownloadUrl && ( + + )} ) : ( <> diff --git a/components/hearing/digitalDemocracyApi.ts b/components/hearing/digitalDemocracyApi.ts index de288629a..aae15445c 100644 --- a/components/hearing/digitalDemocracyApi.ts +++ b/components/hearing/digitalDemocracyApi.ts @@ -31,11 +31,13 @@ export type DDUtterance = { content: string first: string | null last: string | null + party: string | null person_type: string pid: number | null hid: number uid: number file_id: string + // Offset in seconds from the start of the video identified by `file_id`. timestamp: number date: number } @@ -77,7 +79,9 @@ export async function fetchDDUtterances( const body: DDUtterancesResponse = await res.json() const utterances = body.data?.utterances ?? [] - return [...utterances].sort((a, b) => a.timestamp - b.timestamp) + // `date` is an absolute epoch timestamp, unlike `timestamp` which resets + // per video, so it's the only reliable way to sort across multiple videos. + return [...utterances].sort((a, b) => a.date - b.date) } export function speakerName(utterance: DDUtterance): string | null { diff --git a/pages/hearings/browse.tsx b/pages/hearings/browse.tsx index 6896d6a70..77d736d9a 100644 --- a/pages/hearings/browse.tsx +++ b/pages/hearings/browse.tsx @@ -46,9 +46,7 @@ const BrowseHearingsPage = createPage({ {hearings.map(hearing => ( - - {hearing.title} - + {hearing.title} {hearing.date} {hearing.chamber} diff --git a/public/locales/en/hearing.json b/public/locales/en/hearing.json index 8308f1b31..9a49bc1a3 100644 --- a/public/locales/en/hearing.json +++ b/public/locales/en/hearing.json @@ -10,6 +10,7 @@ "download_transcript_x": "Download transcript for {{title}}", "hearing_details": "Hearing details", "house_chair": "House Chair", + "legislator_tag": "Legislator", "member": "Member", "members": "Members", "no": "No",