Skip to content

Commit 0a74d19

Browse files
m1212eStrehk
andauthored
✨ feature: adds a data export for attendance data for committee members (#276)
* 🚧 wip: attendance data export * 🚧 wip: attendance data * 🚧 wip: add fields to export * ✨ feat: add data to import * ✨ feat: enhance presence data export functionality and update GraphQL queries * ✨ feat: streamline layout and regional group declarations in German localization --------- Co-authored-by: Tade Strehk <git@strehk.eu>
1 parent 6bc0c71 commit 0a74d19

File tree

11 files changed

+140
-6
lines changed

11 files changed

+140
-6
lines changed

bun.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"@inlang/cli": "^3.0.10",
1919
"@inlang/paraglide-js": "2.0.11",
2020
"@m1212e/graphql-scalars-houdini": "^0.0.1",
21-
"@m1212e/rumble": "^0.7.10",
21+
"@m1212e/rumble": "^0.7.11",
2222
"@m1212e/sveltekit-oidc": "^0.0.31",
2323
"@sveltejs/adapter-node": "^5.2.12",
2424
"@sveltejs/kit": "^2.20.7",
@@ -255,7 +255,7 @@
255255

256256
"@m1212e/graphql-scalars-houdini": ["@m1212e/graphql-scalars-houdini@0.0.1", "", { "dependencies": { "graphql-scalars": "^1.24" }, "peerDependencies": { "houdini": "^1", "typescript": "^5" } }, "sha512-sbehs8H45vQ5rSo4Md6LxfOu0c0BkxUVEJDAUdofWK4ea1WJf5rytqok03fPhV8K3rC/oIfGk0LAi31X0/OQMw=="],
257257

258-
"@m1212e/rumble": ["@m1212e/rumble@0.7.10", "", { "dependencies": { "@pothos/core": "^4.6.2", "@pothos/plugin-drizzle": "^0.10.2", "@pothos/plugin-smart-subscriptions": "^4.1.2", "graphql-scalars": "^1.24.2", "graphql-yoga": "^5.13.4" }, "peerDependencies": { "drizzle-orm": "^1", "typescript": "^5" } }, "sha512-gQeOguzuaSOFvU4a8EqFMJ+by1W3atQB6LHSUm4d1yDUazB1PeEC72tc5n7Ffhl/nTjPhJzCz1Saw2ol50kiEA=="],
258+
"@m1212e/rumble": ["@m1212e/rumble@0.7.11", "", { "dependencies": { "@pothos/core": "^4.6.2", "@pothos/plugin-drizzle": "^0.10.2", "@pothos/plugin-smart-subscriptions": "^4.1.2", "graphql-scalars": "^1.24.2", "graphql-yoga": "^5.13.4" }, "peerDependencies": { "drizzle-orm": "^1", "typescript": "^5" } }, "sha512-cSUPie7Ma2OhSEgTE5dWwb+YtPosvUmIs34lvZuoupGSviW5QlJTw0sS1a7yNJijS0se/Y+5TiQHykauUhN8Ag=="],
259259

260260
"@m1212e/sveltekit-oidc": ["@m1212e/sveltekit-oidc@0.0.31", "", { "dependencies": { "@sinclair/typebox": "^0.34.33" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-mnQAXDfw6gbUYS8Do1lwlijZNyrk7XMCCRRNhmt95XDkn97Q4gPhXc9+7oKT4vd9MTgpqQJ9WEkiYzMrNg5tTA=="],
261261

messages/de.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,5 +242,6 @@
242242
"download": "Download",
243243
"speakersListNotFound": "Redeliste nicht gefunden",
244244
"create": "Erstellen",
245-
"agendaItemTitle": "Titel des Tagesordnungspunkts"
245+
"agendaItemTitle": "Titel des Tagesordnungspunkts",
246+
"downloadPresenceData": "Anwesenheitsdaten"
246247
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"@inlang/cli": "^3.0.10",
1010
"@inlang/paraglide-js": "2.0.11",
1111
"@m1212e/graphql-scalars-houdini": "^0.0.1",
12-
"@m1212e/rumble": "^0.7.10",
12+
"@m1212e/rumble": "^0.7.11",
1313
"@m1212e/sveltekit-oidc": "^0.0.31",
1414
"@sveltejs/adapter-node": "^5.2.12",
1515
"@sveltejs/kit": "^2.20.7",

schema.graphql

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type CommitteeMember {
5757
committeeId: ID!
5858
createdAt: DateTime!
5959
id: ID!
60+
presenceChangedTimestamps(where: PresenceChangedTimestampWhereInputArgument): [PresenceChangedTimestamp!]!
6061
present: Boolean!
6162
representation(where: RepresentationWhereInputArgument): Representation!
6263
representationId: ID!
@@ -68,6 +69,7 @@ input CommitteeMemberWhereInputArgument {
6869
committeeId: ID
6970
createdAt: DateTime
7071
id: ID
72+
presenceChangedTimestamps: PresenceChangedTimestampWhereInputArgument
7173
present: Boolean
7274
representation: RepresentationWhereInputArgument
7375
representationId: ID
@@ -275,13 +277,34 @@ type Mutation {
275277
updateSpeakersList(id: ID!, isClosed: Boolean, speakingTime: Int, startTimestamp: DateTime, stopTimer: Boolean = false, timeLeft: Int): SpeakersList
276278
}
277279

280+
type PresenceChangedTimestamp {
281+
committeeMember(where: CommitteeMemberWhereInputArgument): CommitteeMember
282+
committeeMemberId: ID!
283+
createdAt: DateTime!
284+
id: ID!
285+
presentSetTo: Boolean!
286+
timestamp: DateTime!
287+
updatedAt: DateTime
288+
}
289+
290+
input PresenceChangedTimestampWhereInputArgument {
291+
committeeMember: CommitteeMemberWhereInputArgument
292+
committeeMemberId: ID
293+
createdAt: DateTime
294+
id: ID
295+
presentSetTo: Boolean
296+
timestamp: DateTime
297+
updatedAt: DateTime
298+
}
299+
278300
type Query {
279301
findFirstAgendaItem(where: AgendaItemWhereInputArgument): AgendaItem!
280302
findFirstCommittee(where: CommitteeWhereInputArgument): Committee!
281303
findFirstCommitteeMember(where: CommitteeMemberWhereInputArgument): CommitteeMember!
282304
findFirstConference(where: ConferenceWhereInputArgument): Conference!
283305
findFirstConferenceMember(where: ConferenceMemberWhereInputArgument): ConferenceMember!
284306
findFirstConferenceUser(where: ConferenceUserWhereInputArgument): ConferenceUser!
307+
findFirstPresenceChangedTimestamp(where: PresenceChangedTimestampWhereInputArgument): PresenceChangedTimestamp!
285308
findFirstRepresentation(where: RepresentationWhereInputArgument): Representation!
286309
findFirstSpeakerOnList(where: SpeakerOnListWhereInputArgument): SpeakerOnList!
287310
findFirstSpeakersList(where: SpeakersListWhereInputArgument): SpeakersList!
@@ -292,6 +315,7 @@ type Query {
292315
findManyConference(where: ConferenceWhereInputArgument): [Conference!]!
293316
findManyConferenceMember(where: ConferenceMemberWhereInputArgument): [ConferenceMember!]!
294317
findManyConferenceUser(where: ConferenceUserWhereInputArgument): [ConferenceUser!]!
318+
findManyPresenceChangedTimestamp(where: PresenceChangedTimestampWhereInputArgument): [PresenceChangedTimestamp!]!
295319
findManyRepresentation(where: RepresentationWhereInputArgument): [Representation!]!
296320
findManySpeakerOnList(where: SpeakerOnListWhereInputArgument): [SpeakerOnList!]!
297321
findManySpeakersList(where: SpeakersListWhereInputArgument): [SpeakersList!]!
@@ -413,6 +437,7 @@ type Subscription {
413437
findFirstConference(where: ConferenceWhereInputArgument): Conference!
414438
findFirstConferenceMember(where: ConferenceMemberWhereInputArgument): ConferenceMember!
415439
findFirstConferenceUser(where: ConferenceUserWhereInputArgument): ConferenceUser!
440+
findFirstPresenceChangedTimestamp(where: PresenceChangedTimestampWhereInputArgument): PresenceChangedTimestamp!
416441
findFirstRepresentation(where: RepresentationWhereInputArgument): Representation!
417442
findFirstSpeakerOnList(where: SpeakerOnListWhereInputArgument): SpeakerOnList!
418443
findFirstSpeakersList(where: SpeakersListWhereInputArgument): SpeakersList!
@@ -423,6 +448,7 @@ type Subscription {
423448
findManyConference(where: ConferenceWhereInputArgument): [Conference!]!
424449
findManyConferenceMember(where: ConferenceMemberWhereInputArgument): [ConferenceMember!]!
425450
findManyConferenceUser(where: ConferenceUserWhereInputArgument): [ConferenceUser!]!
451+
findManyPresenceChangedTimestamp(where: PresenceChangedTimestampWhereInputArgument): [PresenceChangedTimestamp!]!
426452
findManyRepresentation(where: RepresentationWhereInputArgument): [Representation!]!
427453
findManySpeakerOnList(where: SpeakerOnListWhereInputArgument): [SpeakerOnList!]!
428454
findManySpeakersList(where: SpeakersListWhereInputArgument): [SpeakersList!]!

src/api/db/relations.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ export const relations = defineRelations(schema, (r) => ({
5454
from: r.committeeMember.id,
5555
to: r.conferenceUser.committeeMemberId,
5656
optional: true
57+
}),
58+
presenceChangedTimestamps: r.many.presenceChangedTimestamp({
59+
from: r.committeeMember.id,
60+
to: r.presenceChangedTimestamp.committeeMemberId
5761
})
5862
},
5963
conferenceUser: {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { abilityBuilder } from '$api/rumble';
2+
import { isDMUNEmail } from '$api/services/isDMUNEmail';
3+
import { basics } from './basics';
4+
5+
const { arg, ref, pubsub, table } = basics('presenceChangedTimestamp');
6+
7+
abilityBuilder.presenceChangedTimestamp.allow(['read']).when(({ hasRole }) => {
8+
if (hasRole('admin')) {
9+
return 'allow';
10+
}
11+
});

src/api/handlers/register.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ import './speakersList';
1010
import './time';
1111
import './user';
1212
import './import';
13+
import './presenceChangedTimestamp';

src/lib/components/NavbarBurgerMenu.svelte

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33
import ThemeSwitcher from './ThemeSwitcher.svelte';
44
import { m } from '$lib/paraglide/messages';
55
import LanguageSwitcher from './LanguageSwitcher.svelte';
6+
import type { Snippet } from 'svelte';
67
78
interface Props {
89
items: {
910
faIcon: string;
1011
title: string;
1112
href: string;
1213
}[];
14+
CustomListItems?: Snippet;
1315
}
1416
15-
let { items }: Props = $props();
17+
let { items, CustomListItems }: Props = $props();
1618
1719
let menuVisible = $state(false);
1820
</script>
@@ -35,6 +37,9 @@
3537
</a>
3638
</li>
3739
{/each}
40+
{#if CustomListItems}
41+
{@render CustomListItems()}
42+
{/if}
3843
<!-- <div class="divider"></div> -->
3944
<div class="mt-4 flex w-full gap-1">
4045
<ThemeSwitcher />

src/routes/app/[conferenceId]/mission-control/+page.gql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
query MissionControlQuery($conferenceId: ID!) {
22
findFirstConference(where: { id: $conferenceId }) {
33
id
4+
title
45
committees {
56
id
67
name

src/routes/app/[conferenceId]/mission-control/+page.svelte

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import NavbarBurgerMenu from '$lib/components/NavbarBurgerMenu.svelte';
88
import { onMount } from 'svelte';
99
import { MissionControlSubscription } from './missionControlSubscription';
10+
import DownloadPresenceData from './DownloadPresenceData.svelte';
1011
1112
let { data }: { data: PageData } = $props();
1213
@@ -36,7 +37,11 @@
3637
<CurrentTime />
3738
</div>
3839
<div class="flex-none">
39-
<NavbarBurgerMenu items={menubarItems} />
40+
<NavbarBurgerMenu items={menubarItems}>
41+
{#snippet CustomListItems()}
42+
<DownloadPresenceData conferenceTitle={conference?.title} conferenceId={conference?.id} />
43+
{/snippet}
44+
</NavbarBurgerMenu>
4045
</div>
4146
</div>
4247

0 commit comments

Comments
 (0)