Add EP amendment and part votes, hidden from general lists by default
They come from the same responses as final votes. A sitting has over a hundred, so they are flagged part_vote and only appear on request: the vote lists have an option for them, feeds, counts and search chunks leave them out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bf19e503f9
commit
b06f17e587
20 files changed
+176
-47
No files matched your search
@@ -157,7 +157,9 @@
|
||||
"travel": "Reisen & Treffen",
|
||||
"social": "Social Media"
|
||||
},
|
||||
"factionVoteNote": "Im Nationalrat wird meist per Aufstehen abgestimmt; offiziell protokolliert ist dann nur das Stimmverhalten der Fraktion. Bei namentlichen Abstimmungen zeigen wir die eigene Stimme – und ob sie von der Fraktion abweicht.",
|
||||
"showPartVotes": "Auch Änderungsanträge und Teilabstimmungen anzeigen",
|
||||
"hidePartVotes": "Nur Abstimmungen über ganze Texte anzeigen",
|
||||
"factionVoteNote":"Im Nationalrat wird meist per Aufstehen abgestimmt; offiziell protokolliert ist dann nur das Stimmverhalten der Fraktion. Bei namentlichen Abstimmungen zeigen wir die eigene Stimme – und ob sie von der Fraktion abweicht.",
|
||||
"roleCorroborated": "mehrfach belegt",
|
||||
"unverified": "laut Wikidata – nicht amtlich bestätigt",
|
||||
"accountUnverified": "Laut Wikidata – nicht amtlich bestätigt",
|
||||
@@ -223,6 +225,7 @@
|
||||
},
|
||||
"Votes": {
|
||||
"title": "Abstimmungen",
|
||||
"includePartVotes": "Auch Änderungsanträge und Teilabstimmungen (EU-Parlament)",
|
||||
"accepted": "angenommen",
|
||||
"rejected": "abgelehnt",
|
||||
"for": "dafür",
|
||||
|
||||
@@ -122,7 +122,9 @@
|
||||
"travel": "Travel & meetings",
|
||||
"social": "Social media"
|
||||
},
|
||||
"factionVoteNote": "The National Council mostly votes by standing up; then only each faction's vote is recorded. For roll-call votes we show the person's own vote – and whether it differs from their faction.",
|
||||
"showPartVotes": "Also show amendments and part votes",
|
||||
"hidePartVotes": "Show votes on whole texts only",
|
||||
"factionVoteNote":"The National Council mostly votes by standing up; then only each faction's vote is recorded. For roll-call votes we show the person's own vote – and whether it differs from their faction.",
|
||||
"roleCorroborated": "corroborated",
|
||||
"unverified": "per Wikidata – not officially confirmed",
|
||||
"accountUnverified": "According to Wikidata – not officially confirmed",
|
||||
@@ -188,6 +190,7 @@
|
||||
},
|
||||
"Votes": {
|
||||
"title": "Votes",
|
||||
"includePartVotes": "Include amendments and part votes (European Parliament)",
|
||||
"accepted": "accepted",
|
||||
"rejected": "rejected",
|
||||
"for": "for",
|
||||
|
||||
@@ -10,7 +10,7 @@ const PAGE = 50;
|
||||
|
||||
type Props = {
|
||||
params: Promise<{locale: string}>;
|
||||
searchParams: Promise<{party?: string; page?: string; roll_call?: string}>;
|
||||
searchParams: Promise<{party?: string; page?: string; roll_call?: string; parts?: string}>;
|
||||
};
|
||||
|
||||
export async function generateMetadata({params}: Props): Promise<Metadata> {
|
||||
@@ -25,16 +25,20 @@ export default async function VotesPage({params, searchParams}: Props) {
|
||||
const sp = await searchParams;
|
||||
const t = await getTranslations('Votes');
|
||||
const page = Math.max(1, Number(sp.page) || 1);
|
||||
const votes = await api.votes({party: sp.party, roll_call: sp.roll_call ? 'true' : undefined, limit: PAGE, offset: (page - 1) * PAGE});
|
||||
const votes = await api.votes({party: sp.party, roll_call: sp.roll_call ? 'true' : undefined,
|
||||
include_parts: sp.parts ? 'true' : undefined, limit: PAGE, offset: (page - 1) * PAGE});
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader title={t('title')} lede={t('intro')} meta={sp.party ? t('filteredParty', {party: sp.party}) : undefined} />
|
||||
<FilterBar id="votes" active={countActive(sp.roll_call)} resetHref={sp.party ? `/abstimmungen?party=${sp.party}` : '/abstimmungen'}
|
||||
<FilterBar id="votes" active={countActive(sp.roll_call, sp.parts)} resetHref={sp.party ? `/abstimmungen?party=${sp.party}` : '/abstimmungen'}
|
||||
hidden={{party: sp.party}}>
|
||||
<label className="field field--check">
|
||||
<input type="checkbox" name="roll_call" value="1" defaultChecked={Boolean(sp.roll_call)} /> {t('onlyRollCall')}
|
||||
</label>
|
||||
<label className="field field--check">
|
||||
<input type="checkbox" name="parts" value="1" defaultChecked={Boolean(sp.parts)} /> {t('includePartVotes')}
|
||||
</label>
|
||||
</FilterBar>
|
||||
<VoteLegend />
|
||||
<VoteList votes={votes} />
|
||||
|
||||
@@ -48,7 +48,7 @@ const GLANCE: [string, ClaimType[], Tab][] = [
|
||||
|
||||
type Props = {
|
||||
params: Promise<{locale: string; slug: string}>;
|
||||
searchParams: Promise<{tab?: string; since?: string; until?: string}>;
|
||||
searchParams: Promise<{tab?: string; since?: string; until?: string; parts?: string}>;
|
||||
};
|
||||
|
||||
async function loadPerson(slug: string): Promise<Person> {
|
||||
@@ -70,7 +70,7 @@ export async function generateMetadata({params}: Props): Promise<Metadata> {
|
||||
export default async function PersonPage({params, searchParams}: Props) {
|
||||
const {locale, slug} = await params;
|
||||
setRequestLocale(locale);
|
||||
const {tab: rawTab, since, until} = await searchParams;
|
||||
const {tab: rawTab, since, until, parts} = await searchParams;
|
||||
const tab: Tab = rawTab && rawTab in TABS ? (rawTab as Tab) : 'overview';
|
||||
const t = await getTranslations('Person');
|
||||
const tp = await getTranslations('Persons');
|
||||
@@ -217,7 +217,10 @@ export default async function PersonPage({params, searchParams}: Props) {
|
||||
{tab === 'votes' && (
|
||||
<section>
|
||||
<Notice tone="info">{t('factionVoteNote')}</Notice>
|
||||
<VoteList votes={await api.personVotes(slug)} />
|
||||
<p className="small">
|
||||
<Link href={parts ? href('votes') : `${href('votes')}&parts=1`}>{t(parts ? 'hidePartVotes' : 'showPartVotes')}</Link>
|
||||
</p>
|
||||
<VoteList votes={await api.personVotes(slug, Boolean(parts))} />
|
||||
</section>
|
||||
)}
|
||||
|
||||
|
||||
+2
-2
@@ -74,9 +74,9 @@ export const api = {
|
||||
persons: (params: Params) => get<T.PersonListItem[]>('/api/v1/persons', params),
|
||||
person: (slug: string) => get<T.PersonDetail>(`/api/v1/persons/${enc(slug)}`),
|
||||
personNetwork: (slug: string) => get<T.Network>(`/api/v1/persons/${enc(slug)}/network`),
|
||||
personVotes: async (slug: string) => {
|
||||
personVotes: async (slug: string, includeParts = false) => {
|
||||
const prefs = await getPrefs();
|
||||
return get<T.PersonVote[]>(`/api/v1/persons/${enc(slug)}/votes`, {topics: prefs.topics});
|
||||
return get<T.PersonVote[]>(`/api/v1/persons/${enc(slug)}/votes`, {topics: prefs.topics, include_parts: includeParts || undefined});
|
||||
},
|
||||
former: (params: Params) => get<T.FormerPerson[]>('/api/v1/former', params),
|
||||
|
||||
|
||||
Reference in new issue
Block a user