From a47bd7b126efb90f515259da33c34540d64a90d1 Mon Sep 17 00:00:00 2001 From: Richard Liu Date: Fri, 22 Nov 2024 16:36:51 -0800 Subject: [PATCH] feat: add imageOptions for lemonade --- .../pipelines/LemonadePipeline.ts | 40 +++++++++++++++++++ .../src/genericIssuanceTypes.ts | 22 +++++----- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/apps/passport-server/src/services/generic-issuance/pipelines/LemonadePipeline.ts b/apps/passport-server/src/services/generic-issuance/pipelines/LemonadePipeline.ts index 3d9452192e..a8b04431c1 100644 --- a/apps/passport-server/src/services/generic-issuance/pipelines/LemonadePipeline.ts +++ b/apps/passport-server/src/services/generic-issuance/pipelines/LemonadePipeline.ts @@ -13,6 +13,7 @@ import { BadgeConfig, CONTACT_EVENT_NAME, GenericIssuanceSendPipelineEmailResponseValue, + ImageOptions, LemonadePipelineDefinition, LemonadePipelineEventConfig, LemonadePipelineTicketTypeConfig, @@ -586,6 +587,37 @@ export class LemonadePipeline implements BasePipeline { }); } + private imageOptionsToImageUrl( + imageOptions: ImageOptions | undefined, + isCheckedIn: boolean + ): string | undefined { + if (!imageOptions) return undefined; + if (imageOptions.requireCheckedIn && !isCheckedIn) return undefined; + return imageOptions.imageUrl; + } + + private atomToQrCodeOverrideImageUrl( + ticketAtom: LemonadeAtom + ): string | undefined { + return this.getEventById(ticketAtom.lemonadeEventId).imageOptions + ?.qrCodeOverrideImageUrl; + } + + private atomToImageUrl(ticketAtom: LemonadeAtom): string | undefined { + return this.imageOptionsToImageUrl( + this.getEventById(ticketAtom.lemonadeEventId).imageOptions, + ticketAtom.checkinDate !== undefined + ); + } + + private atomToEventLocation(atom: LemonadeAtom): string | undefined { + return this.getEventById(atom.lemonadeEventId).imageOptions?.eventLocation; + } + + private atomToEventStartDate(atom: LemonadeAtom): string | undefined { + return this.getEventById(atom.lemonadeEventId).imageOptions?.eventStartDate; + } + private async manualTicketToTicketData( client: PoolClient, manualTicket: ManualTicket, @@ -608,6 +640,10 @@ export class LemonadePipeline implements BasePipeline { attendeeName: manualTicket.attendeeName, attendeeSemaphoreId: sempahoreId, isConsumed: checkIn ? true : false, + imageUrl: this.imageOptionsToImageUrl(event.imageOptions, !!checkIn), + qrCodeOverrideImageUrl: event.imageOptions?.qrCodeOverrideImageUrl, + eventStartDate: event.imageOptions?.eventStartDate, + eventLocation: event.imageOptions?.eventLocation, isRevoked: false, timestampSigned: Date.now(), timestampConsumed: checkIn ? checkIn.timestamp.getTime() : 0, @@ -1160,6 +1196,10 @@ export class LemonadePipeline implements BasePipeline { timestampConsumed: atom.checkinDate instanceof Date ? atom.checkinDate.getTime() : 0, timestampSigned: Date.now(), + imageUrl: this.atomToImageUrl(atom), + qrCodeOverrideImageUrl: this.atomToQrCodeOverrideImageUrl(atom), + eventStartDate: this.atomToEventStartDate(atom), + eventLocation: this.atomToEventLocation(atom), attendeeSemaphoreId: semaphoreId, isConsumed: atom.checkinDate instanceof Date, isRevoked: false, // Not clear what concept this maps to in Lemonade diff --git a/packages/lib/passport-interface/src/genericIssuanceTypes.ts b/packages/lib/passport-interface/src/genericIssuanceTypes.ts index b4fef2cb9f..f4247408e6 100644 --- a/packages/lib/passport-interface/src/genericIssuanceTypes.ts +++ b/packages/lib/passport-interface/src/genericIssuanceTypes.ts @@ -182,6 +182,14 @@ const SemaphoreGroupListSchema = z { message: "Semaphore group names must be unique" } ); +const ImageOptionsSchema = z.object({ + imageUrl: z.string(), + requireCheckedIn: z.boolean(), + qrCodeOverrideImageUrl: z.string().optional(), + eventStartDate: z.string().optional(), + eventLocation: z.string().optional() +}); + /** * Generic Issuance-specific ticket type configuration - roughly corresponds to a * 'Product' in Pretix-land. @@ -206,7 +214,11 @@ const LemonadePipelineEventConfigSchema = z.object({ /** * Roughly translates to Products in {@link EdDSATicketPCD}. */ - ticketTypes: z.array(LemonadePipelineTicketTypeConfigSchema) + ticketTypes: z.array(LemonadePipelineTicketTypeConfigSchema), + /** + * Options to configure displaying an image instead of the QR code + */ + imageOptions: ImageOptionsSchema.optional() }); /** @@ -275,14 +287,6 @@ const FeedIssuanceOptionsSchema = z.object({ export type FeedIssuanceOptions = z.infer; -const ImageOptionsSchema = z.object({ - imageUrl: z.string(), - requireCheckedIn: z.boolean(), - qrCodeOverrideImageUrl: z.string().optional(), - eventStartDate: z.string().optional(), - eventLocation: z.string().optional() -}); - export type ImageOptions = z.infer; const LemonadePipelineOptionsSchema = BasePipelineOptionsSchema.extend({