Skip to content
Merged

next #488

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 50 additions & 38 deletions apps/api/src/routes/exports/photos.archive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import archiver from 'archiver'
import type { Context } from 'hono'
import { stream } from 'hono/streaming'
import mime from 'mime'
import { Readable } from 'node:stream'
import { z } from 'zod'
import prisma from '../../prisma.js'
import { openFileStream } from '../../services/file/helpers/getFileUrl.js'
Expand Down Expand Up @@ -119,54 +118,67 @@ export async function veranstaltungPhotoArchive(ctx: Context<{ Variables: Author

const zip = archiver('zip')

zip.on('warning', function (err) {
if (err.code === 'ENOENT') {
console.warn(err)
} else {
throw err
}
})

zip.on('error', function (err) {
throw err
})

ctx.status(201)
ctx.header('Content-Type', 'application/zip')
ctx.header('Content-Disposition', `attachment; filename="${mode === 'flat' ? 'FotosForAutomation' : 'Fotos'}.zip"`)

zip.append(`Gesamtzahl Fotos: ${anmeldungen.length}`, { name: `${baseDirectory}/README.txt` })

for (const { person, unterveranstaltung } of anmeldungen) {
if (!person.photo) {
continue
}
return stream(ctx, async (s) => {
zip.on('data', (chunk) => {
/* eslint-disable @typescript-eslint/no-floating-promises */
s.write(chunk)
})

const stream = await openFileStream(person.photo)
for (const { person, unterveranstaltung } of anmeldungen) {
if (!person.photo) {
continue
}

const directory = `${unterveranstaltung.veranstaltung.name}/${unterveranstaltung.gliederung.name}`
const basename = mode === 'group' ? `${person.firstname} ${person.lastname}` : person.id
const extension = mime.getExtension(person.photo.mimetype ?? 'text/plain')
const stream = await openFileStream(person.photo)

zip.append(stream, {
name:
mode === 'group'
? `${baseDirectory}/${directory}/${basename}.${extension}`
: `Fotos/${person.photo.id}.${extension}`,
date: person.photo.createdAt,
})
}
stream.on('end', () => {
stream.destroy()
})

if (mode === 'flat') {
const buffer = buildSheet(anmeldungen, account.person)
zip.append(buffer, {
name: 'Datenzusammenführung.xlsx',
})
}
const directory = `${unterveranstaltung.veranstaltung.name}/${unterveranstaltung.gliederung.name}`
const basename = mode === 'group' ? `${person.firstname} ${person.lastname}` : person.id
const extension = mime.getExtension(person.photo.mimetype ?? 'text/plain')

zip.append(stream, {
name:
mode === 'group'
? `${baseDirectory}/${directory}/${basename}.${extension}`
: `Fotos/${person.photo.id}.${extension}`,
date: person.photo.createdAt,
})
}

await zip.finalize()
if (mode === 'flat') {
const buffer = buildSheet(anmeldungen, account.person)
zip.append(buffer, {
name: 'Datenzusammenführung.xlsx',
})
}

return stream(ctx, async (s) => {
await s.pipe(Readable.toWeb(zip))
/* eslint-disable @typescript-eslint/no-floating-promises */
zip.finalize()

await new Promise<void>((resolve, reject) => {
zip.on('warning', function (err) {
if (err.code === 'ENOENT') {
console.warn(err)
} else {
reject(err)
}
})

zip.once('end', () => {
resolve()
})
zip.once('error', (err) => {
reject(err)
})
})
})
}
4 changes: 1 addition & 3 deletions apps/api/src/routes/exports/teilnehmendenliste.sheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export async function veranstaltungTeilnehmendenliste(ctx: Context<{ Variables:
unterveranstaltung: {
gliederungId: gliederung?.id,
},
status: 'BESTAETIGT',
},
select: {
id: true,
Expand Down Expand Up @@ -114,8 +113,7 @@ export async function veranstaltungTeilnehmendenliste(ctx: Context<{ Variables:
'#': anmeldung.id,

Veranstaltung: anmeldung.unterveranstaltung.veranstaltung.name,
Ausschreibung:
anmeldung.unterveranstaltung.beschreibung?.substring(0, 30) || anmeldung.unterveranstaltung.gliederung.name,
Ausschreibung: anmeldung.unterveranstaltung.gliederung.name,
'Art der Ausschreibung': anmeldung.unterveranstaltung.type,

Status: AnmeldungStatusMapping[anmeldung.status].human,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,7 @@ export const unterveranstaltungListProcedure = defineProtectedQueryProcedure({
},
_count: {
select: {
Anmeldung: {
where: {
status: 'BESTAETIGT',
},
},
Anmeldung: true,
},
},
meldebeginn: true,
Expand Down
6 changes: 3 additions & 3 deletions apps/frontend/src/views/Anmeldung/AnmeldungFormGeneral.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { FaceFrownIcon } from '@heroicons/vue/24/outline'
import { useAsyncState } from '@vueuse/core'
import { defineProps, ref, watch, withDefaults } from 'vue'
import { ref, watch } from 'vue'
import { useRouter } from 'vue-router'

import { apiClient } from '@/api'
Expand Down Expand Up @@ -29,11 +29,11 @@
if (!unterveranstaltung) {
return undefined
}
// TODO: Nur Felder für die Position anzeigen

return apiClient.customFields.list.query({
entity: 'unterveranstaltung',
entityId: unterveranstaltung.value.id,
position: 'PUBLIC_ANMELDUNG',
position: props.isPublic ? 'PUBLIC_ANMELDUNG' : 'INTERN_ANMELDUNG',
})
}, [])

Expand Down Expand Up @@ -114,7 +114,7 @@
<div class="text-lg font-semibold">Teilnahmebedingungen der Gliederung</div>
<div
class="prose dark:prose-invert"
v-html="sanitizeHtml(unterveranstaltung?.bedingungen)"

Check warning on line 117 in apps/frontend/src/views/Anmeldung/AnmeldungFormGeneral.vue

View workflow job for this annotation

GitHub Actions / 🔍 turbo-checks

'v-html' directive can lead to XSS attack
/>

<hr class="my-10" />
Expand All @@ -122,7 +122,7 @@
<div class="text-lg font-semibold">Allgemeine Teilnahmebedingungen</div>
<div
class="prose dark:prose-invert"
v-html="sanitizeHtml(unterveranstaltung?.veranstaltung?.teilnahmeBedingungenPublic)"

Check warning on line 125 in apps/frontend/src/views/Anmeldung/AnmeldungFormGeneral.vue

View workflow job for this annotation

GitHub Actions / 🔍 turbo-checks

'v-html' directive can lead to XSS attack
/>
</div>
</template>
Expand All @@ -137,7 +137,7 @@

<div
class="prose dark:prose-invert"
v-html="sanitizeHtml(unterveranstaltung?.veranstaltung?.datenschutz)"

Check warning on line 140 in apps/frontend/src/views/Anmeldung/AnmeldungFormGeneral.vue

View workflow job for this annotation

GitHub Actions / 🔍 turbo-checks

'v-html' directive can lead to XSS attack
/>
</div>
</template>
Expand Down
Loading