Create a Single Page Application using Microsoft Graph API and Angular to show data from Teams, SharePoint, Planner, Email and Calendar
Kislay Sinha
Product Owner at Epiroc - Connected Platform - Digital Business | Ex - CGI | Ex - Infosys
Instructions and code for creating a Single Page Application using Angular that fetches data from the Microsoft Graph API. The application will display the user's last 5 emails, 5 calendar entries, 5 last accessed SharePoint sites, and 5 last Planner tasks.
## Instructions:
1. Set up the Angular Project:
```bash
# Install Angular CLI (if not already installed)
npm install -g @angular/cli
# Create a new Angular project
ng new email-calendar-app
cd email-calendar-app
```
2. Implement the Backend using Node.js with Express:
Create a new folder called `server` within the root directory of the Angular project.
```bash
mkdir server
cd server
npm init -y
npm install express body-parser cors node-fetch @microsoft/microsoft-graph-client
```
3. Set up Microsoft Graph API Application:
Go to the Azure portal (https://portal.azure.com) and create a new application to obtain the required credentials (Client ID, Client Secret).
4. Write the Backend Code:
In the `server` folder, create a file named `app.js`.
```javascript
// server/app.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const fetch = require('node-fetch');
const { Client } = require('@microsoft/microsoft-graph-client');
const app = express();
app.use(bodyParser.json());
app.use(cors());
const clientId = 'YOUR_CLIENT_ID'; // Replace with your client ID
const clientSecret = 'YOUR_CLIENT_SECRET'; // Replace with your client secret
const scope = 'User.Read Mail.Read Calendars.Read Sites.Read.All Tasks.Read'; // Required scopes for API calls
const tenantId = 'YOUR_TENANT_ID'; // Replace with your Azure tenant ID
app.get('/api/getData', async (req, res) => {
?const accessToken = await getAccessToken();
?if (!accessToken) {
??return res.status(401).json({ error: 'Failed to obtain access token' });
?}
?const promises = [
??fetchLastEmails(accessToken),
??fetchCalendarEntries(accessToken),
??fetchLastAccessedSites(accessToken),
??fetchPlannerTasks(accessToken)
?];
?try {
??const [emails, calendarEntries, sites, tasks] = await Promise.all(promises);
??return res.json({ emails, calendarEntries, sites, tasks });
?} catch (err) {
??console.error('Error fetching data:', err);
??return res.status(500).json({ error: 'Error fetching data from Microsoft Graph API' });
?}
});
async function getAccessToken() {
?const tokenEndpoint = `https://login.microsoftonline.com/${tenantId}/oauth2/token`;
?const response = await fetch(tokenEndpoint, {
??method: 'POST',
??headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
??body: `client_id=${clientId}&client_secret=${clientSecret}&scope=${scope}&grant_type=client_credentials`
?});
?if (!response.ok) {
??console.error('Error obtaining access token:', response.statusText);
??return null;
?}
?const data = await response.json();
?return data.access_token;
}
async function fetchLastEmails(accessToken) {
?const client = Client.init({
??authProvider: (done) => {
???done(null, accessToken);
??}
?});
?try {
??const messages = await client.api('/me/messages')
???.top(5)
???.orderby('receivedDateTime DESC')
???.select('subject')
???.get();
??return messages.value;
?} catch (err) {
??console.error('Error fetching last emails:', err);
??return [];
?}
}
async function fetchCalendarEntries(accessToken) {
?const client = Client.init({
??authProvider: (done) => {
???done(null, accessToken);
??}
?});
?try {
??const events = await client.api('/me/events')
???.top(5)
???.orderby('start/dateTime DESC')
???.select('subject,start,end')
???.get();
??return events.value;
?} catch (err) {
??console.error('Error fetching calendar entries:', err);
??return [];
?}
}
async function fetchLastAccessedSites(accessToken) {
?const client = Client.init({
??authProvider: (done) => {
???done(null, accessToken);
??}
?});
?try {
??const sites = await client.api('/me/insights/used')
???.top(5)
???.select('resourceReference')
???.get();
??return sites.value.map(site => site.resourceReference);
领英推荐
?} catch (err) {
??console.error('Error fetching last accessed SharePoint sites:', err);
??return [];
?}
}
async function fetchPlannerTasks(accessToken) {
?const client = Client.init({
??authProvider: (done) => {
???done(null, accessToken);
??}
?});
?try {
??const tasks = await client.api('/me/planner/tasks')
???.top(5)
???.orderby('createdDateTime DESC')
???.select('title')
???.get();
??return tasks.value;
?} catch (err) {
??console.error('Error fetching Planner tasks:', err);
??return [];
?}
}
const port = 3000;
app.listen(port, () => {
?console.log(`Server is running on https://localhost:${port}`);
});
```
5. Write the Frontend Code:
In the `src/app` folder of the Angular project, create a new component called `dashboard`.
```bash
ng generate component dashboard
```
In the `dashboard.component.ts` file, make the following changes:
```typescript
// src/app/dashboard/dashboard.component.ts
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
?selector: 'app-dashboard',
?templateUrl: './dashboard.component.html',
?styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
?emails: any[];
?calendarEntries: any[];
?sites: any[];
?tasks: any[];
??
?constructor(private http: HttpClient) { }
?ngOnInit(): void {
??this.getData();
?}
?getData(): void {
??this.http.get<any>('https://localhost:3000/api/getData').subscribe(
???data => {
????this.emails = data.emails;
????this.calendarEntries = data.calendarEntries;
????this.sites = data.sites;
????this.tasks = data.tasks;
???},
???error => {
????console.error('Error fetching data:', error);
???}
??);
?}
}
```
In the `dashboard.component.html` file, display the fetched data:
```html
<!-- src/app/dashboard/dashboard.component.html -->
<h2>Last 5 Emails:</h2>
<ul>
?<li *ngFor="let email of emails">{{ email.subject }}</li>
</ul>
<h2>Last 5 Calendar Entries:</h2>
<ul>
?<li *ngFor="let entry of calendarEntries">{{ entry.subject }}</li>
</ul>
<h2>Last 5 Accessed SharePoint Sites:</h2>
<ul>
?<li *ngFor="let site of sites">{{ site.name }}</li>
</ul>
<h2>Last 5 Planner Tasks:</h2>
<ul>
?<li *ngFor="let task of tasks">{{ task.title }}</li>
</ul>
```
6. Update `app.module.ts` to include the HttpClientModule:
```typescript
//
?src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http'; // Add this line
import { AppComponent } from './app.component';
import { DashboardComponent } from './dashboard/dashboard.component';
@NgModule({
?declarations: [
??AppComponent,
??DashboardComponent
?],
?imports: [
??BrowserModule,
??HttpClientModule // Add this line
?],
?providers: [],
?bootstrap: [AppComponent]
})
export class AppModule { }
```
7. Run the Application:
In the root directory of the Angular project, run the Angular application:
```bash
ng serve
```
Ensure the backend (Node.js server) is also running on `https://localhost:3000`.
Now, when you visit `https://localhost:4200` in your web browser, you should see the dashboard displaying the last 5 emails, calendar entries, accessed SharePoint sites, and Planner tasks fetched from the Microsoft Graph API. Replace the placeholders in the `app.js` file with your actual credentials and tenant ID.