diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fdc7d1f..cfcf6ce9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Nylas Java SDK Changelog +## [Unreleased] + +### Added +* Support for `logo` field in `EmailTemplate` class to specify a custom logo URL for booking emails +* Support for `show_nylas_branding` field in `EmailTemplate` class to control Nylas branding visibility in booking emails + ## [2.10.0] - Release 2025-06-12 ### Added diff --git a/src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt b/src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt index c67bb771..8fb9f287 100644 --- a/src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt +++ b/src/main/kotlin/com/nylas/models/ConfigurationSchedulerSettings.kt @@ -262,7 +262,61 @@ data class EmailTemplate( */ @Json(name = "booking_confirmed") val bookingConfirmed: BookingConfirmedTemplate? = null, -) + /** + * URL of a custom logo to appear in booking emails. + */ + @Json(name = "logo") + val logo: String? = null, + /** + * Boolean flag to toggle Nylas branding visibility. + */ + @Json(name = "show_nylas_branding") + val showNylasBranding: Boolean? = null, +) { + /** + * Builder for [EmailTemplate]. + */ + class Builder { + private var bookingConfirmed: BookingConfirmedTemplate? = null + private var logo: String? = null + private var showNylasBranding: Boolean? = null + + /** + * Set the configurable settings specifically for booking confirmed emails. + * + * @param bookingConfirmed Configurable settings specifically for booking confirmed emails. + * @return The builder. + */ + fun bookingConfirmed(bookingConfirmed: BookingConfirmedTemplate) = apply { this.bookingConfirmed = bookingConfirmed } + + /** + * Set the URL of a custom logo to appear in booking emails. + * + * @param logo URL of a custom logo to appear in booking emails. + * @return The builder. + */ + fun logo(logo: String) = apply { this.logo = logo } + + /** + * Set the boolean flag to toggle Nylas branding visibility. + * + * @param showNylasBranding Boolean flag to toggle Nylas branding visibility. + * @return The builder. + */ + fun showNylasBranding(showNylasBranding: Boolean) = apply { this.showNylasBranding = showNylasBranding } + + /** + * Build the [EmailTemplate]. + * + * @return The [EmailTemplate] + */ + fun build() = EmailTemplate( + bookingConfirmed, + logo, + showNylasBranding, + ) + } +} /** * Class representation of booking confirmed template settings. diff --git a/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt b/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt index d7c06f91..e1fee7a7 100644 --- a/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt +++ b/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt @@ -182,6 +182,54 @@ class ConfigurationsTest { assertEquals("Test", config.participants.first().name) assertEquals("", config.participants.first().timezone) } + + @Test + fun `EmailTemplate with new fields serializes properly`() { + val adapter = JsonHelper.moshi().adapter(EmailTemplate::class.java) + val jsonBuffer = Buffer().writeUtf8( + """ + { + "booking_confirmed": { + "title": "Custom Booking Title", + "body": "Thank you for booking with us!" + }, + "logo": "https://example.com/logo.png", + "show_nylas_branding": false + } + """.trimIndent(), + ) + + val emailTemplate = adapter.fromJson(jsonBuffer)!! + assertIs(emailTemplate) + assertEquals("https://example.com/logo.png", emailTemplate.logo) + assertEquals(false, emailTemplate.showNylasBranding) + assertEquals("Custom Booking Title", emailTemplate.bookingConfirmed?.title) + assertEquals("Thank you for booking with us!", emailTemplate.bookingConfirmed?.body) + + // Test serialization back to JSON + val serializedJson = adapter.toJson(emailTemplate) + assert(serializedJson.contains("\"logo\":\"https://example.com/logo.png\"")) + assert(serializedJson.contains("\"show_nylas_branding\":false")) + } + + @Test + fun `EmailTemplate Builder works correctly`() { + val bookingConfirmed = BookingConfirmedTemplate( + title = "Custom Title", + body = "Custom Body", + ) + + val emailTemplate = EmailTemplate.Builder() + .bookingConfirmed(bookingConfirmed) + .logo("https://company.com/logo.svg") + .showNylasBranding(true) + .build() + + assertEquals("https://company.com/logo.svg", emailTemplate.logo) + assertEquals(true, emailTemplate.showNylasBranding) + assertEquals("Custom Title", emailTemplate.bookingConfirmed?.title) + assertEquals("Custom Body", emailTemplate.bookingConfirmed?.body) + } } @Nested @@ -402,5 +450,85 @@ class ConfigurationsTest { assertEquals("v3/grants/$grantId/scheduling/configurations/$configId", pathCaptor.firstValue) assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) } + + @Test + fun `creating a configuration with custom email template calls requests with the correct params`() { + val adapter = JsonHelper.moshi().adapter(CreateConfigurationRequest::class.java) + val participantCalendarIds = ArrayList() + participantCalendarIds.add("primary") + + val configurationAvailabilityParticipant = ConfigurationAvailabilityParticipant.Builder().calendarIds(participantCalendarIds).build() + + val configurationBookingParticipant = ConfigurationBookingParticipant.Builder().calendarId("primary").build() + + val configurationParticipant = ConfigurationParticipant.Builder("test@nylas.com") + .availability(configurationAvailabilityParticipant) + .booking(configurationBookingParticipant) + .name("Test Participant") + .isOrganizer(true) + .build() + + val configurationAvailability = ConfigurationAvailability.Builder().intervalMinutes(30).build() + + val configurationEventBooking = ConfigurationEventBooking.Builder().title("Test Event Booking").build() + + // Create EmailTemplate with new logo and showNylasBranding fields + val emailTemplate = EmailTemplate.Builder() + .logo("https://company.com/custom-logo.png") + .showNylasBranding(false) + .bookingConfirmed( + BookingConfirmedTemplate( + title = "Your Meeting is Confirmed", + body = "Thank you for booking! We look forward to meeting with you.", + ), + ) + .build() + + // Create scheduler settings with the email template + val schedulerSettings = ConfigurationSchedulerSettings.Builder() + .emailTemplate(emailTemplate) + .availableDaysInFuture(14) + .minBookingNotice(120) + .build() + + val participants = ArrayList() + participants.add(configurationParticipant) + + val createConfigurationRequest = CreateConfigurationRequest.Builder( + participants, + configurationAvailability, + configurationEventBooking, + ) + .name("Configuration with Custom Email Template") + .scheduler(schedulerSettings) + .build() + + configurations.create(grantId, createConfigurationRequest) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val requestBodyCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executePost>( + pathCaptor.capture(), + typeCaptor.capture(), + requestBodyCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/scheduling/configurations", pathCaptor.firstValue) + assertEquals(Types.newParameterizedType(Response::class.java, Configuration::class.java), typeCaptor.firstValue) + + val serializedRequest = adapter.toJson(createConfigurationRequest) + assertEquals(serializedRequest, requestBodyCaptor.firstValue) + + // Verify that the JSON contains the new EmailTemplate fields + assert(serializedRequest.contains("\"logo\":\"https://company.com/custom-logo.png\"")) + assert(serializedRequest.contains("\"show_nylas_branding\":false")) + assert(serializedRequest.contains("\"booking_confirmed\"")) + assert(serializedRequest.contains("Your Meeting is Confirmed")) + } } }