reactjssharepointmicrosoft-graph-apioffice365spfx

SPFX get Microsoft Outlook room events using Graph API


I am building an SPFx app and I need to read the rooms and their events from Outlook, our company has 25 conference rooms that can be used to book events in a SharePoint calendar, we need to make sure the room is available in outlook and also be able create the event in outlook when submitted in the SharePoint form

I was able to get the list of all the rooms using the SharePoint context and querying the Microsoft Graph API like this:

 const [outlookRooms, setOutlookRooms] = useState<any[]>([]);

 React.useEffect(() =>{
const context = props.context;

      context.msGraphClientFactory
      .getClient('3')
      .then((client: MSGraphClientV3): void => {      
        client
          .api('/places/microsoft.graph.room')
          .get((response: any, error: any) => {
            console.log(response);
            console.log(error);
             setOutlookRooms(response);            
   
        });
      });

 },[]);

that part is working fine but when I try to get the room events I am getting a 404, this is my code for getting the room events:

 const [roomEvents, setRoomEvents] = useState<any[]>([]);  

React.useEffect(() =>{
const context = props.context;

context.msGraphClientFactory
    .getClient('3')
    .then((client: MSGraphClientV3): void => {      
      client
        .api('/groups/roomid/calendarView?startDateTime=2024-01-01T19:00:00-08:00&endDateTime=2024-06-01T19:00:00.00-08:00')
        .get((response: any) => {
          setRoomEvents(response.value);            
          console.log(response);
      })
      
      ;
    });
 },[]);

Solution

  • I couldn't find a way to get the events for rooms directly from the SPFX, what I end up doing was to create an Azure Function to get the events from Outlook, then I can call the azure function from the SPFX app, you have to enable CORS in the azure function to accept SharePoint calls, the azure function looks like this:

    import { app, HttpRequest, HttpResponseInit } from "@azure/functions";
    import axios from "axios";
    import { Context } from "vm";
    
    const tenantId = "mytenantid";
    const clientId = "appclientid";
    const clientSecret = "appclientsecret";
    const scopes = "https://graph.microsoft.com/.default";
    
    export async function GetEvents(req: HttpRequest, context: Context): Promise<HttpResponseInit> {
        context.log(`Http function processed request for url "${req.url}"`);   
        
        
        const startDate = req.query.get('startdate') || await req.text();    
        const endDate = req.query.get('enddate') || await req.text();
        const roomEmail = req.query.get('roomemail') || await req.text();       
    
            if(startDate ==='' || endDate ==='' || roomEmail ===''){
                return { body: 'Parameters missing startdate: ' + startDate + 'enddate: ' +endDate+ 'room: '+ roomEmail}
            }       
    
            const params = new URLSearchParams();
            params.append('client_id', clientId);
            params.append('client_secret', clientSecret);
            params.append('scope', scopes);
            params.append('grant_type', 'client_credentials');
    
            let loginResponse = await axios.post(`https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/token`, params);
            
            if (loginResponse.status == 200) {
                let accessToken: string = loginResponse.data.access_token;
    
                let getPlaceResponse = await axios({
                    method: 'post',
                    url: `https://graph.microsoft.com/v1.0/users/{useridwithpermissionstorooms}/calendar/getSchedule`,
                    headers: { Authorization: "Bearer " + accessToken },
                    data: {
                        Schedules: [roomEmail],
                        StartTime: {
                            dateTime: startDate,
                            timeZone: "America/Denver"
                        },
                        EndTime: {
                            dateTime: endDate,
                            timeZone: "America/Denver"
                        },
                        availabilityViewInterval: "30"
                    }
                });
    
                if(getPlaceResponse.status == 200){
                    context.res = getPlaceResponse.data.value[0].scheduleItems;
                }
                else{
                    context.res = {
                        status: 500,
                        body: {
                            message: "Get Schedule Error"
                        }
                    };
                }            
            }
            else {
                context.res = {
                    status: 500,
                    body: {
                        message: "Auth Error"
                    }
                };
            }  
    
       let result = JSON.stringify(context.res);
        return {body: result};
    
    };
    
    app.http('GetEvents', {
        methods: ['GET', 'POST'],
        authLevel: 'anonymous',
        handler: GetEvents
    });