Outlook 日历不使用 FullCalendar 呈现

问题描述 投票:0回答:1

我正在开发一个应用程序来使用fullcalendar查看我的Outlook日历上的事件,问题是我登录到Microsoft,原则上一切都是正确的,我返回我的网站但日历没有生成,更重要的是,如果我再次单击登录按钮会显示一条消息,表明登录仍在进行中

(errorCode === "interaction_in_progress")
并且我得到控制台日志'im在else(accounts.length)'中。

这是我的代码,我找不到导致日历和事件无法加载的原因。

<div id="calendar"></div>

<script>
    let msalInstance;
    const loginRequest = {
        scopes: ["User.Read", "Calendars.Read", "Calendars.Read.Shared"]
    };

    async function mostrarCalendarioOutlook() {
        console.log('I am inside of mostrarCalendarioOutlook');
        try {
            if (!msalInstance) {
                throw new Error("msalInstance is not initialized");
            }
            const accounts = msalInstance.getAllAccounts();
            if (accounts.length > 0) {
                console.log('Dentro del if (accounts.length > 0)');
                const account = accounts[0];
                const tokenResponse = await msalInstance.acquireTokenSilent({
                    account,
                    scopes: ["User.Read", "Calendars.Read", "Calendars.Read.Shared"]
                });
                const events = await getCalendarEvents(tokenResponse.accessToken);
                console.log('initializing render calendar function');
                renderCalendar(events);
            } else {                
                console.log('im inside the else (accounts.length)');
                await msalInstance.loginRedirect(loginRequest);
            }
        } catch (error) {                        
            handleError(error);            
        }
    }

    function handleError(error) {
        if (error.errorCode === "interaction_in_progress") {
            Swal.fire({
                    icon: 'info',
                    title: 'Process in progress',
                    text: 'The login process is in progress. Please wait for it to complete.',
                    allowOutsideClick: false
                });
        } else if (error.errorCode === "consent_required" || error.errorCode === "interaction_required") {
            Swal.fire({
                icon: 'error',
                title: 'Necessary permissions',
                text: 'The administrator must grant the necessary permissions to access the calendars. Contact the administrator.'
            });
        } else if (error.errorCode === "access_denied") {
            Swal.fire({
                icon: 'error',
                title: 'Access denied',
                text: 'The requested data could not be accessed. Check permissions and try again.'
            });
        } else {
            Swal.fire({
                icon: 'error',
                title: 'Authentication error',
                text: 'An error occurred during authentication. Please try again later.'
            });
            console.error('Error during authentication:', error);
        }
    }    

    document.addEventListener('DOMContentLoaded', async function() {                
        try {
            const msalConfig = {
                auth: {
                    clientId: "Client_ID", 
                    authority: "https://login.microsoftonline.com/common",                    
                    redirectUri: "redirect_Uri",
                    popUp: true
                }
            };

            msalInstance = new msal.PublicClientApplication(msalConfig);            

            //EVENTS
            async function getCalendarEvents(accessToken) {
                console.log('im inside of getCalendarEvents');
                const response = await fetch('https://graph.microsoft.com/v1.0/me/events', {
                    headers: {
                        'Authorization': `Bearer ${accessToken}`
                    }
                });

                if (!response.ok) {
                    const errorText = await response.text();
                    console.error(`Error getting calendar events: ${response.status} ${response.statusText}`, errorText);
                    throw new Error('Error getting calendar events');
                }

                const data = await response.json();
                const events = [];

                function adjustToLocalTime(dateTime) {
                    const date = new Date(dateTime);
                    const timeZoneOffset = date.getTimezoneOffset() * 60000;
                    return new Date(date.getTime() - timeZoneOffset).toISOString();
                }

                const recurringEvents = data.value.filter(event => event.recurrence && event.recurrence.pattern);

                recurringEvents.forEach(event => {
                    const startDate = new Date(event.start.dateTime);
                    const endDate = new Date(event.end.dateTime);
                    const recurrence = event.recurrence.pattern;
                    let instanceDate = new Date(startDate);
                    const endRecurrenceDate = event.recurrence.range && event.recurrence.range.endDate ? new Date(event.recurrence.range.endDate) : null;

                    while (!endRecurrenceDate || instanceDate <= endRecurrenceDate) {
                        if (!recurrence.daysOfWeek) {
                            const adjustedStartDate = new Date(instanceDate);
                            adjustedStartDate.setHours(startDate.getHours());
                            adjustedStartDate.setMinutes(startDate.getMinutes());

                            const adjustedEndDate = new Date(instanceDate);
                            adjustedEndDate.setHours(endDate.getHours());
                            adjustedEndDate.setMinutes(endDate.getMinutes());

                            if (adjustedStartDate <= endRecurrenceDate || !endRecurrenceDate) {
                                events.push({
                                    title: event.subject,
                                    start: adjustToLocalTime(adjustedStartDate.toISOString()),
                                    end: adjustToLocalTime(adjustedEndDate.toISOString()),
                                    allDay: event.isAllDay
                                });
                            }

                            switch (recurrence.type) {
                                case "daily":
                                    instanceDate.setDate(instanceDate.getDate() + recurrence.interval);
                                    break;
                                case "absoluteMonthly":
                                    instanceDate.setMonth(instanceDate.getMonth() + recurrence.interval);
                                    break;
                                case "absoluteYearly":
                                    instanceDate.setFullYear(instanceDate.getFullYear() + recurrence.interval);
                                    break;
                            }

                            continue;
                        }

                        const daysOfWeekIndices = (recurrence.daysOfWeek || []).map(day => {
                            switch (day.toLowerCase()) {
                                case "monday":
                                    return 1;
                                case "tuesday":
                                    return 2;
                                case "wednesday":
                                    return 3;
                                case "thursday":
                                    return 4;
                                case "friday":
                                    return 5;
                                case "saturday":
                                    return 6;
                                case "sunday":
                                    return 0;
                            }
                        });

                        daysOfWeekIndices.forEach(dayIndex => {
                            let tempDate = new Date(instanceDate);
                            while (tempDate.getDay() !== dayIndex) {
                                tempDate.setDate(tempDate.getDate() + 1);
                            }

                            if (tempDate >= startDate && (!endRecurrenceDate || tempDate <= endRecurrenceDate)) {
                                const adjustedStartDate = new Date(tempDate);
                                adjustedStartDate.setHours(startDate.getHours());
                                adjustedStartDate.setMinutes(startDate.getMinutes());

                                const adjustedEndDate = new Date(tempDate);
                                adjustedEndDate.setHours(endDate.getHours());
                                adjustedEndDate.setMinutes(endDate.getMinutes());

                                if (adjustedStartDate <= endRecurrenceDate || !endRecurrenceDate) {
                                    events.push({
                                        title: event.subject,
                                        start: adjustToLocalTime(adjustedStartDate.toISOString()),
                                        end: adjustToLocalTime(adjustedEndDate.toISOString()),
                                        allDay: event.isAllDay
                                    });
                                }
                            }
                        });

                        instanceDate.setDate(instanceDate.getDate() + 7 * recurrence.interval);
                    }

                    if (endRecurrenceDate && recurrence.daysOfWeek) {
                        const tempDate = new Date(endRecurrenceDate);
                        const endRecurrenceDay = tempDate.toLocaleString('en-US', {
                            weekday: 'long'
                        }).toLowerCase();
                        if (recurrence.daysOfWeek.includes(endRecurrenceDay)) {
                            const adjustedStartDate = new Date(tempDate);
                            adjustedStartDate.setHours(startDate.getHours());
                            adjustedStartDate.setMinutes(startDate.getMinutes());

                            const adjustedEndDate = new Date(tempDate);
                            adjustedEndDate.setHours(endDate.getHours());
                            adjustedEndDate.setMinutes(endDate.getMinutes());

                            if (adjustedStartDate.getTime() !== endRecurrenceDate.getTime()) {
                                events.push({
                                    title: event.subject,
                                    start: adjustToLocalTime(adjustedStartDate.toISOString()),
                                    end: adjustToLocalTime(adjustedEndDate.toISOString()),
                                    allDay: event.isAllDay
                                });
                            }
                        }
                    }
                });

                const singleEvents = data.value.filter(event => !event.recurrence);
                singleEvents.forEach(event => {
                    events.push({
                        title: event.subject,
                        start: adjustToLocalTime(event.start.dateTime),
                        end: adjustToLocalTime(event.end.dateTime),
                        allDay: event.isAllDay
                    });
                });               

                return events;
            }

            async function handleLogoutClick() {
                console.log('Signing out Microsoft...');
                Swal.fire({
                    title: 'Signing out...',
                    allowOutsideClick: false,
                    didOpen: () => {
                        Swal.showLoading();
                    },
                });

                try {
                    const accounts = await msalInstance.getAllAccounts();
                    if (accounts.length === 0) {
                        Swal.close();
                        return;
                    }

                    const respuesta = await msalInstance.logoutPopup({
                        account: accounts[0],
                    });

                    if (respuesta) {
                        localStorage.setItem('logoutCompleted', 'true');
                        console.log('Microsoft session closed successfully');
                    } else {
                        localStorage.setItem('logoutCompleted', 'false');
                        console.log('The session was not logged out');
                    }

                    Swal.close();

                } catch (error) {
                    Swal.fire({
                        icon: 'error',
                        title: 'Error logout',
                        text: 'An error occurred while trying to log out. Please try again later.'
                    });
                    console.log('Error signing out Microsoft', error);
                } finally {
                    Swal.close();
                }
            }

            function renderCalendar(events) {
                console.log('I enter the renderCalendar function');
                const calendarEl = document.getElementById('calendar');
                const calendar = new FullCalendar.Calendar(calendarEl, {
                    customButtons: {
                        myCustomButton: {
                            text: 'Refrescar',
                            click: async function() {
                                console.log('Updating Calendar...');
                                Swal.fire({
                                    title: 'Updating Calendar...',
                                    allowOutsideClick: false,
                                    didOpen: () => {
                                        Swal.showLoading();
                                    }
                                });

                                try {
                                    const accounts = await msalInstance.getAllAccounts();
                                    if (accounts.length === 0) {
                                        await msalInstance.loginRedirect(loginRequest);
                                        return;
                                    }

                                    const response = await msalInstance.acquireTokenSilent({
                                        account: accounts[0],
                                        scopes: ["User.Read", "Calendars.Read", "Calendars.Read.Shared"]
                                    });

                                    if (response !== null) {
                                        const accessToken = response.accessToken;
                                        const events = await getCalendarEvents(accessToken);
                                        renderCalendar(events);
                                        Swal.close();
                                        console.log('Calendar refreshed successfully');
                                    } else {
                                        console.error('Could not get access token.');
                                        console.log('Calendar NOT refreshed');
                                        Swal.close();
                                    }
                                } catch (error) {
                                    console.log('Error when refreshing calendar');
                                    handleError(error);
                                }
                            }
                        },
                        logout: {
                            text: 'Cerrar Sesión',
                            click: function() {
                                handleLogoutClick();
                            }
                        }
                    },
                    headerToolbar: {
                        left: 'prev,next today myCustomButton logout',
                        center: 'title',
                        right: 'dayGridMonth,timeGridWeek,timeGridDay'
                    },
                    buttonText: {
                        today: 'Hoy',
                        month: 'Mes',
                        week: 'Semana',
                        day: 'Día',
                        list: 'Lista'
                    },
                    initialView: 'dayGridMonth',
                    locale: <?php echo '"' . session('language') . '"'; ?>,
                    firstDay: 1,
                    events: events,
                    dayMaxEvents: true,
                    eventClick: function(info) {
                        const event = info.event;
                        const title = event.title;
                        const start = event.start;
                        const end = event.end;
                        const allDay = event.allDay;
                        const location = event.extendedProps.location;

                        const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;

                        const startFormatted = start.toLocaleString('es-ES', {
                            timeZone: timeZone
                        });
                        const endFormatted = end ? end.toLocaleString('es-ES', {
                            timeZone: timeZone
                        }) : 'Evento de todo el día';

                        let content = `<h2>${title}</h2>`;
                        if (!allDay) {
                            content += `<p><strong>Inicio:</strong> ${startFormatted}</p>`;
                            content += `<p><strong>Fin:</strong> ${endFormatted}</p>`;
                        } else {
                            content += `<p><strong>Evento de todo el día</strong></p>`;
                        }
                        if (location) {
                            content += `<p><strong>Ubicación:</strong> ${location}</p>`;
                        }

                        Swal.fire({
                            title: 'Información del Evento',
                            html: content,
                            icon: 'info'
                        });

                        console.log('Infomacion:' + info.event);
                        console.log('Titulo:' + title);
                        console.log('Inicio:' + start);
                        console.log('Fin:' + end);
                        console.log('Evento Diario:' + allDay);
                    }
                });
                calendar.render();
            }
        } catch (error) {
            console.error('Error during initialization:', error);
            Swal.fire({
                icon: 'error',
                title: 'Initialization error',
                text: 'An error occurred while loading the configuration. Please try again later.'
            });
        }
    });
</script>

非常感谢!!

javascript azure outlook azure-active-directory office365
1个回答
0
投票

由于多次登录尝试或页面导航,可能会出现错误

(errorCode === "interaction_in_progress")

发布答案以帮助社区:

在您的场景中,问题是因为登录按钮和日历位于同一 URI 上。

  • 当登录过程重定向回应用程序时,会导致页面重新加载,从而中断应用程序的流程。

要解决该问题,请检查以下内容:

  • 配置单独的重定向 URL:在 Azure 门户中配置不同的重定向 URI 以处理 Microsoft 登录,并确保它不会干扰主应用程序 URI。
  • 创建独立的登录按钮:将登录按钮移至导航栏,这将为登录过程创建一个单独的页面。
https://graph.microsoft.com/v1.0/me/events

enter image description here

因此,请确保登录过程不会干扰应用程序的状态,这样做身份验证流程将完好无损,并且您将能够使用获取的事件成功呈现日历。

© www.soinside.com 2019 - 2024. All rights reserved.