feat: update Office365 getMainTimeZone to handle new Graph API format and convert Windows timezones to IANA (#23763)
* feat: update Office365 getMainTimeZone to handle new Graph API format and convert Windows timezones to IANA - Handle new Graph API response format with 'value' field containing Windows timezone names - Add windows-iana dependency for timezone conversion from Windows to IANA format - Maintain backward compatibility with legacy direct string response format - Add proper error handling with fallback to original timezone name if conversion fails - Log conversion details for debugging and monitoring Co-Authored-By: morgan@cal.com <morgan@cal.com> * fix: example app select default value * fixup! fix: example app select default value * fix: preserve legacy string timezone behavior, only convert new object format - Address GitHub comments from supalarry about behavior change concerns - Preserve original behavior: return legacy string responses as-is without conversion - Only convert Windows timezones from new Graph API object format - Add explanatory comments about API format evolution - Restructure conditional logic to handle formats independently Co-Authored-By: morgan@cal.com <morgan@cal.com> * trigger CI with ready-for-e2e label Co-Authored-By: morgan@cal.com <morgan@cal.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: morgan@cal.com <morgan@cal.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
This commit is contained in:
co-authored by
Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
morgan@cal.com <morgan@cal.com>
Morgan
parent
fc159fb9ea
commit
6f5b8ead75
@@ -1,5 +1,6 @@
|
||||
import type { Calendar as OfficeCalendar, User, Event } from "@microsoft/microsoft-graph-types-beta";
|
||||
import type { DefaultBodyType } from "msw";
|
||||
import { findIana } from "windows-iana";
|
||||
|
||||
import { MSTeamsLocationType } from "@calcom/app-store/constants";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
@@ -688,20 +689,58 @@ export default class Office365CalendarService implements Calendar {
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the main timezone from Office365 mailbox settings.
|
||||
* Handles both legacy string format and new Graph API object format due to API evolution.
|
||||
* Legacy format: returns string timezone as-is (preserves existing behavior)
|
||||
* New format: converts Windows timezone from {"value": "Windows Timezone"} to IANA format
|
||||
*/
|
||||
async getMainTimeZone(): Promise<string> {
|
||||
try {
|
||||
const response = await this.fetcher(`${await this.getUserEndpoint()}/mailboxSettings/timeZone`);
|
||||
const timezone = await handleErrorsJson<string>(response);
|
||||
const timezoneResponse = await handleErrorsJson<string | { value: string }>(response);
|
||||
|
||||
if (!timezone || typeof timezone !== "string") {
|
||||
if (typeof timezoneResponse === "object" && timezoneResponse !== null && "value" in timezoneResponse) {
|
||||
const windowsTimezoneName = timezoneResponse.value;
|
||||
this.log.info("timezone found in outlook mailbox settings (new format)", {
|
||||
windowsTimezoneName,
|
||||
});
|
||||
|
||||
try {
|
||||
const ianaTimezone = findIana(windowsTimezoneName);
|
||||
if (ianaTimezone && ianaTimezone.length > 0) {
|
||||
const convertedTimezone = ianaTimezone[0];
|
||||
this.log.info("Successfully converted Windows timezone to IANA", {
|
||||
windowsTimezoneName,
|
||||
convertedTimezone,
|
||||
});
|
||||
return convertedTimezone;
|
||||
} else {
|
||||
this.log.warn("Could not convert Windows timezone to IANA, using original value", {
|
||||
windowsTimezoneName,
|
||||
});
|
||||
return windowsTimezoneName;
|
||||
}
|
||||
} catch (conversionError) {
|
||||
this.log.warn("Error converting Windows timezone to IANA, using original value", {
|
||||
windowsTimezoneName,
|
||||
conversionError,
|
||||
});
|
||||
return windowsTimezoneName;
|
||||
}
|
||||
}
|
||||
|
||||
if (!timezoneResponse || typeof timezoneResponse !== "string") {
|
||||
this.log.warn("No timezone found in outlook mailbox settings, defaulting to Europe/London", {
|
||||
timezone,
|
||||
timezoneResponse,
|
||||
});
|
||||
return "Europe/London";
|
||||
}
|
||||
this.log.info("timezone found in outlook mailbox settings", { timezone });
|
||||
|
||||
return timezone;
|
||||
this.log.info("timezone found in outlook mailbox settings (legacy format)", {
|
||||
timezone: timezoneResponse,
|
||||
});
|
||||
return timezoneResponse;
|
||||
} catch (error) {
|
||||
this.log.error("Error getting main timezone from Office365 Calendar", { error });
|
||||
throw error;
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"dependencies": {
|
||||
"@calcom/lib": "workspace:*",
|
||||
"@calcom/prisma": "workspace:*",
|
||||
"msw": "^2.7.0"
|
||||
"msw": "^2.7.0",
|
||||
"windows-iana": "^5.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@calcom/types": "workspace:*"
|
||||
|
||||
@@ -73,7 +73,7 @@ export default function App({ Component, pageProps }: AppProps) {
|
||||
}
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
if (!!selectedUser) {
|
||||
if (selectedUser) {
|
||||
setAccessToken(selectedUser.accessToken);
|
||||
setUserEmail(selectedUser.email);
|
||||
setUsername(selectedUser.username);
|
||||
@@ -83,13 +83,15 @@ export default function App({ Component, pageProps }: AppProps) {
|
||||
return (
|
||||
<div className={`${poppins.className} text-black`}>
|
||||
{options.length > 0 && (
|
||||
<Select defaultValue={selectedUser} onChange={setSelectedUser} options={options} />
|
||||
<Select
|
||||
defaultValue={options.find((opt: TUser | null) => opt?.email.includes("lauris"))}
|
||||
onChange={(opt: TUser | null) => setSelectedUser(opt)}
|
||||
options={options}
|
||||
/>
|
||||
)}
|
||||
<CalProvider
|
||||
accessToken={accessToken}
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
clientId={process.env.NEXT_PUBLIC_X_CAL_ID ?? ""}
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
options={{ apiUrl: process.env.NEXT_PUBLIC_CALCOM_API_URL ?? "", refreshUrl: "/api/refresh" }}>
|
||||
{email ? (
|
||||
<>
|
||||
|
||||
@@ -3750,6 +3750,7 @@ __metadata:
|
||||
"@calcom/prisma": "workspace:*"
|
||||
"@calcom/types": "workspace:*"
|
||||
msw: ^2.7.0
|
||||
windows-iana: ^5.1.0
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@@ -49166,6 +49167,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"windows-iana@npm:^5.1.0":
|
||||
version: 5.1.0
|
||||
resolution: "windows-iana@npm:5.1.0"
|
||||
checksum: 0dc9ababde5f839e83a4bcd448347d8da563efd9e23ce61ac777e9992774ff85de2a9f343f87b80b37b181742fe4d783cff3ba39191cfedb6357ae7d5f58aadc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"winston-transport@npm:^4.5.0, winston-transport@npm:^4.9.0":
|
||||
version: 4.9.0
|
||||
resolution: "winston-transport@npm:4.9.0"
|
||||
|
||||
Reference in New Issue
Block a user