diff --git a/frontend/pages/admin/IntegrationsPage/cards/Calendars/Calendars.tsx b/frontend/pages/admin/IntegrationsPage/cards/Calendars/Calendars.tsx index de7c79a139b0..da22ea4801a4 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/Calendars/Calendars.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/Calendars/Calendars.tsx @@ -33,7 +33,7 @@ const API_KEY_JSON_PLACEHOLDER = `{ "type": "service_account", "project_id": "fleet-in-your-calendar", "private_key_id": "", - "private_key": "-----BEGIN PRIVATE KEY-----\n\n-----END PRIVATE KEY-----\n", + "private_key": "-----BEGIN PRIVATE KEY----\\n\\n-----END PRIVATE KEY-----\\n", "client_email": "fleet-calendar-events@fleet-in-your-calendar.iam.gserviceaccount.com", "client_id": "", "auth_uri": "https://accounts.google.com/o/oauth2/auth", @@ -58,6 +58,16 @@ interface ICalendarsFormData { apiKeyJson?: string; } +// Used to surface error.message in UI of unknown error type +type ErrorWithMessage = { + message: string; + [key: string]: unknown; +}; + +const isErrorWithMessage = (error: unknown): error is ErrorWithMessage => { + return (error as ErrorWithMessage).message !== undefined; +}; + const baseClass = "calendars-integration"; const Calendars = (): JSX.Element => { @@ -103,7 +113,18 @@ const Calendars = (): JSX.Element => { errors.apiKeyJson = "API key JSON must be present"; } if (!curFormData.domain && !!curFormData.apiKeyJson) { - errors.apiKeyJson = "Domain must be present"; + errors.domain = "Domain must be present"; + } + if (curFormData.apiKeyJson) { + try { + JSON.parse(curFormData.apiKeyJson); + } catch (e: unknown) { + if (isErrorWithMessage(e)) { + errors.apiKeyJson = e.message.toString(); + } else { + throw e; + } + } } return errors; }; @@ -277,6 +298,7 @@ const Calendars = (): JSX.Element => { placeholder={API_KEY_JSON_PLACEHOLDER} ignore1password inputClassName={`${baseClass}__api-key-json`} + error={formErrors.apiKeyJson} /> { /> } + error={formErrors.domain} />