diff --git a/common/slack/blocks.ts b/common/slack/blocks.ts index 07a90b398..eb3fc603d 100644 --- a/common/slack/blocks.ts +++ b/common/slack/blocks.ts @@ -6,33 +6,44 @@ export interface SlackBlock { fields?: { type: 'mrkdwn'; text: string }[]; } -// Unfortunately Slack only supports tables with two columns: -export function table(name: string, colA: string, colB: string, entries: [string, string][]): SlackBlock { - return { - type: 'section', - text: { type: 'mrkdwn', text: name }, - fields: [ - { - type: 'mrkdwn', - text: bold(colA), - }, - { - type: 'mrkdwn', - text: bold(colB), - }, - ...entries.flatMap( - (entry) => - [ - { - type: 'mrkdwn', - text: entry[0], - }, - { - type: 'mrkdwn', - text: entry[1], - }, - ] as const - ), - ], - }; +// Unfortunately Slack only supports tables with two columns, and with a maximum of 10 rows +export function table(name: string, colA: string, colB: string, entries: [string, string][]): SlackBlock[] { + const result: SlackBlock[] = []; + + for (let i = 0; i < entries.length; i += 4) { + const chunk = entries.slice(i, i + 4); + result.push({ + type: 'section', + text: { type: 'mrkdwn', text: i === 0 ? name : ' ' }, + fields: [ + ...(i === 0 + ? ([ + { + type: 'mrkdwn', + text: bold(colA), + }, + { + type: 'mrkdwn', + text: bold(colB), + }, + ] as const) + : []), + ...chunk.flatMap( + (entry) => + [ + { + type: 'mrkdwn', + text: entry[0], + }, + { + type: 'mrkdwn', + text: entry[1], + }, + ] as const + ), + ], + }); + } + + return result; } diff --git a/graphql/match/fields.ts b/graphql/match/fields.ts index ea56ab1cb..8f90bb6de 100644 --- a/graphql/match/fields.ts +++ b/graphql/match/fields.ts @@ -50,25 +50,6 @@ export class ExtendedFieldsMatchResolver { return getOverlappingSubjects(pupil, student); } - // Unfortunately it is difficult to define conditional access on a user's email without raising field level access restrictions, - // which we don't really want as the email is very sensitive data. - // Thus in hope that a proper Chat will soon replace email communication, manually release the fields through this indirection: - @FieldResolver((returns) => String) - @Authorized(Role.OWNER) - async pupilEmail(@Root() match: Match) { - return await ( - await prisma.pupil.findUniqueOrThrow({ where: { id: match.pupilId }, select: { email: true } }) - ).email; - } - - @FieldResolver((returns) => String) - @Authorized(Role.OWNER) - async studentEmail(@Root() match: Match) { - return await ( - await prisma.student.findUniqueOrThrow({ where: { id: match.studentId }, select: { email: true } }) - ).email; - } - @FieldResolver((returns) => [Appointment]) @Authorized(Role.ADMIN, Role.OWNER) async appointments(@Ctx() context: GraphQLContext, @Root() match: Match) { diff --git a/jobs/slack-statistics.ts b/jobs/slack-statistics.ts index 6511e24fe..35483f20d 100644 --- a/jobs/slack-statistics.ts +++ b/jobs/slack-statistics.ts @@ -87,9 +87,7 @@ export async function postStatisticsToSlack() { createdAt: { gte: begin, lte: end }, knowsCoronaSchoolFrom: { notIn: [''] }, }, - _count: { - createdAt: true, - }, + _count: true, }); let instructorKnowsCoronaSchoolFromTable: [string, string][] = []; @@ -129,6 +127,7 @@ export async function postStatisticsToSlack() { every: { start: { lt: end } }, some: { start: { gte: begin, lt: end } }, }, + published: true, }, }); @@ -145,7 +144,7 @@ export async function postStatisticsToSlack() { await sendToSlack(SLACK_CHANNEL.PublicStatistics, { blocks: [ - table(`Statistiken vom ${begin} zum ${end}`, 'Name', 'Wert', [ + ...table(`Statistiken vom ${begin} zum ${end}`, 'Name', 'Wert', [ ['Anzahl registrierter Schüler*innen', '' + pupilRegisteredCount], ['Anzahl registrierter Helfer*innen', '' + studentsRegisteredCount], ['Anzahl erfolgreicher Screenings Schüler*innen', '' + pupilScreeningSuccessCount + ' von ' + pupilScreeningCount], @@ -155,9 +154,9 @@ export async function postStatisticsToSlack() { ['Anzahl erstellter Kurse', '' + subcourseCreatedCount], ['Anzahl Match-Termine', '' + matchAppointmentCount], ]), - table('Von uns gehört durch... (Helfer*innen)', 'Name', 'Wert', tutorKnowsCoronaSchoolFromTable), - table('Von uns gehört durch... (Kursleiter*innen)', 'Name', 'Wert', instructorKnowsCoronaSchoolFromTable), - table('Anzahl der belegten Plätze in den aktuellen Kursen', 'Name', 'Wert', subcourseSeatsTakenTable), + ...table('Von uns gehört durch... (Helfer*innen)', 'Name', 'Wert', tutorKnowsCoronaSchoolFromTable), + ...table('Von uns gehört durch... (Kursleiter*innen)', 'Name', 'Wert', instructorKnowsCoronaSchoolFromTable), + ...table('Anzahl der belegten Plätze in den aktuellen Kursen', 'Name', 'Wert', subcourseSeatsTakenTable), ], }); }