Créez des applications React à une seule page avec Microsoft Graph
Ce didacticiel vous apprend à créer une application React page unique qui utilise l’API Microsoft Graph pour récupérer les informations de calendrier d’un utilisateur.
Conseil
Si vous préférez simplement télécharger le didacticiel terminé, vous pouvez télécharger ou cloner le GitHub complet.
Conditions préalables
Avant de commencer ce didacticiel, vous devez avoir installéNode.js et Sons sur votre ordinateur de développement. Si vous n’avez pas de Node.js, consultez les liens précédents pour obtenir les options de téléchargement.
Vous devez également avoir un compte Microsoft personnel avec une boîte aux lettres sur Outlook.com, ou un compte scolaire ou scolaire Microsoft. Si vous n’avez pas de compte Microsoft, deux options s’offrent à vous pour obtenir un compte gratuit :
- Vous pouvez vous inscrire à un nouveau compte Microsoft personnel.
- Vous pouvez vous inscrire au programme Microsoft 365 développeur pour obtenir un abonnement Microsoft 365 gratuit.
Notes
Ce didacticiel a été écrit avec Node version 14.15.0 et La version 1.22.10 de Ce didacticiel. Les étapes de ce guide peuvent fonctionner avec d’autres versions, mais elles n’ont pas été testées.
Commentaires
N’hésitez pas à nous faire part de vos commentaires sur ce didacticiel dans GitHub référentiel.
Créer une application React à une seule page
Dans cette section, vous allez créer une application React de messagerie.
Ouvrez votre interface de ligne de commande( CLI), accédez à un répertoire dans lequel vous avez le droit de créer des fichiers et exécutez les commandes suivantes pour créer une application React nouvelle.
yarn create react-app graph-tutorial --template typescript
Une fois la commande finale, modifiez le répertoire graph-tutorial'** dans votre CLI et exécutez la commande suivante pour démarrer un serveur web local.
yarn start
Notes
Si Ce n’est pas le cas, vous pouvez l’utiliser
npm start
à la place.
Votre navigateur par défaut s’ouvre https://localhost:3000/ avec une page de React par défaut. Si votre navigateur ne s’ouvre pas, ouvrez-le et recherchez-le pour vérifier https://localhost:3000/ que la nouvelle application fonctionne.
Ajouter des packages de nœuds
Avant de passer à la suite, installez des packages supplémentaires que vous utiliserez ultérieurement :
- react-router-dom pour le routage déclaratif à l’intérieur de l React applet.
- bootstrap pour les styles et les composants courants.
- react-bootstrap pour React composants basés sur Bootstrap.
- date-fns pour la mise en forme des dates et heures.
- windows-iana pour la traduction Windows fuseaux horaires au format IANA.
- msal-react pour l’authentification Azure Active Directory et la récupération des jetons d’accès.
- microsoft-graph-client pour effectuer des appels à Microsoft Graph.
Exécutez la commande suivante dans votre CLI.
yarn add react-router-dom@5.2.0 bootstrap@5.0.1 react-bootstrap@2.0.0-beta.4 windows-iana@5.0.2
yarn add date-fns@2.22.1 date-fns-tz@1.1.4 @azure/msal-react@1.0.1 @azure/msal-browser@2.16.1 @microsoft/microsoft-graph-client@3.0.0
yarn add -D @types/react-router-dom@5.1.8 @types/microsoft-graph
Concevoir l’application
Commencez par créer un contexte pour l’application.
Créez un fichier dans le répertoire ./src nommé AppContext.tsx et ajoutez les
import
instructions suivantes.import React, { useContext, createContext, useState, MouseEventHandler, useEffect} from 'react'; import { AuthCodeMSALBrowserAuthenticationProvider } from '@microsoft/microsoft-graph-client/authProviders/authCodeMsalBrowser'; import { InteractionType, PublicClientApplication } from '@azure/msal-browser'; import { useMsal } from '@azure/msal-react';
Ajoutez le code suivant.
Ajoutez la fonction suivante à la fin de ./src/AppContext.tsx.
function useProvideAppContext() { const [user, setUser] = useState<AppUser | undefined>(undefined); const [error, setError] = useState<AppError | undefined>(undefined); const displayError = (message: string, debug?: string) => { setError({message, debug}); } const clearError = () => { setError(undefined); } const authProvider = undefined; const signIn = async () => { // TODO }; const signOut = async () => { // TODO }; return { user, error, signIn, signOut, displayError, clearError, authProvider }; }
Vous terminerez l’implémentation de ce contexte dans les sections ultérieures.
Créez une barre de navigation pour l’application. Créez un fichier dans
./src
le répertoire nommé etNavBar.tsx
ajoutez le code suivant.import React from 'react'; import { NavLink as RouterNavLink } from 'react-router-dom'; import { Button, Collapse, Container, Navbar, NavbarToggler, NavbarBrand, Nav, NavItem, NavLink, UncontrolledDropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; import '@fortawesome/fontawesome-free/css/all.css'; interface NavBarProps { isAuthenticated: boolean; authButtonMethod: any; user: any; } interface NavBarState { isOpen: boolean; } function UserAvatar(props: any) { // If a user avatar is available, return an img tag with the pic if (props.user.avatar) { return <img src={props.user.avatar} alt="user" className="rounded-circle align-self-center mr-2" style={{ width: '32px' }}></img>; } // No avatar available, return a default icon return <i className="far fa-user-circle fa-lg rounded-circle align-self-center mr-2" style={{ width: '32px' }}></i>; } function AuthNavItem(props: NavBarProps) { // If authenticated, return a dropdown with the user's info and a // sign out button if (props.isAuthenticated) { return ( <UncontrolledDropdown> <DropdownToggle nav caret> <UserAvatar user={props.user} /> </DropdownToggle> <DropdownMenu right> <h5 className="dropdown-item-text mb-0">{props.user.displayName}</h5> <p className="dropdown-item-text text-muted mb-0">{props.user.email}</p> <DropdownItem divider /> <DropdownItem onClick={props.authButtonMethod}>Sign Out</DropdownItem> </DropdownMenu> </UncontrolledDropdown> ); } // Not authenticated, return a sign in link return ( <NavItem> <Button onClick={props.authButtonMethod} className="btn-link nav-link border-0" color="link">Sign In</Button> </NavItem> ); } export default class NavBar extends React.Component<NavBarProps, NavBarState> { constructor(props: NavBarProps) { super(props); this.toggle = this.toggle.bind(this); this.state = { isOpen: false }; } toggle() { this.setState({ isOpen: !this.state.isOpen }); } render() { // Only show calendar nav item if logged in let calendarLink = null; if (this.props.isAuthenticated) { calendarLink = ( <NavItem> <RouterNavLink to="/calendar" className="nav-link" exact>Calendar</RouterNavLink> </NavItem> ); } return ( <div> <Navbar color="dark" dark expand="md" fixed="top"> <Container> <NavbarBrand href="/">React Graph Tutorial</NavbarBrand> <NavbarToggler onClick={this.toggle} /> <Collapse isOpen={this.state.isOpen} navbar> <Nav className="mr-auto" navbar> <NavItem> <RouterNavLink to="/" className="nav-link" exact>Home</RouterNavLink> </NavItem> {calendarLink} </Nav> <Nav className="justify-content-end" navbar> <NavItem> <NavLink href="https://developer.microsoft.com/graph/docs/concepts/overview" target="_blank"> <i className="fas fa-external-link-alt mr-1"></i> Docs </NavLink> </NavItem> <AuthNavItem isAuthenticated={this.props.isAuthenticated} authButtonMethod={this.props.authButtonMethod} user={this.props.user} /> </Nav> </Collapse> </Container> </Navbar> </div> ); } }
Créez une page d’accueil pour l’application. Créez un fichier dans
./src
le répertoire nommé etWelcome.tsx
ajoutez le code suivant.import React from 'react'; import { Button, Jumbotron } from 'reactstrap'; interface WelcomeProps { isAuthenticated: boolean; authButtonMethod: any; user: any; } interface WelcomeState { isOpen: boolean; } function WelcomeContent(props: WelcomeProps) { // If authenticated, greet the user if (props.isAuthenticated) { return ( <div> <h4>Welcome {props.user.displayName}!</h4> <p>Use the navigation bar at the top of the page to get started.</p> </div> ); } // Not authenticated, present a sign in button return <Button color="primary" onClick={props.authButtonMethod}>Click here to sign in</Button>; } export default class Welcome extends React.Component<WelcomeProps, WelcomeState> { render() { return ( <Jumbotron> <h1>React Graph Tutorial</h1> <p className="lead"> This sample app shows how to use the Microsoft Graph API to access Outlook and OneDrive data from React </p> <WelcomeContent isAuthenticated={this.props.isAuthenticated} user={this.props.user} authButtonMethod={this.props.authButtonMethod} /> </Jumbotron> ); } }
Créez un message d’erreur pour afficher les messages à l’utilisateur. Créez un fichier dans
./src
le répertoire nommé etErrorMessage.tsx
ajoutez le code suivant.import React from 'react'; import { Alert } from 'reactstrap'; interface ErrorMessageProps { debug: string; message: string; } export default class ErrorMessage extends React.Component<ErrorMessageProps> { render() { let debug = null; if (this.props.debug) { debug = <pre className="alert-pre border bg-light p-2"><code>{this.props.debug}</code></pre>; } return ( <Alert color="danger"> <p className="mb-3">{this.props.message}</p> {debug} </Alert> ); } }
Ouvrez le fichier
./src/index.css
et remplacez l’intégralité de son contenu par ce qui suit.body { padding-top: 4.5rem; } .alert-pre { word-wrap: break-word; word-break: break-all; white-space: pre-wrap; }
Ouvrez
./src/App.tsx
et remplacez tout son contenu par ce qui suit.import { BrowserRouter as Router, Route } from 'react-router-dom'; import { Container } from 'react-bootstrap'; import { MsalProvider } from '@azure/msal-react' import { IPublicClientApplication } from '@azure/msal-browser'; import ProvideAppContext from './AppContext'; import ErrorMessage from './ErrorMessage'; import NavBar from './NavBar'; import Welcome from './Welcome'; import 'bootstrap/dist/css/bootstrap.css'; export default function App() { return( <ProvideAppContext> <Router> <NavBar /> <Container> <ErrorMessage /> <Route exact path="/" render={(props) => <Welcome {...props} /> } /> </Container> </Router> </ProvideAppContext> ); }
Ajoutez un fichier image de votre choix nommé no-profile-photo.png dans le répertoire ./public/images. Cette image est utilisée comme photo de l’utilisateur lorsque l’utilisateur n’a pas de photo dans Microsoft Graph.
Enregistrez toutes vos modifications et redémarrez l’application. L’application doit maintenant avoir une apparence très différente.
Inscrire l’application sur le portail
Dans cet exercice, vous allez créer une inscription d’application web Azure AD à l’aide Azure Active Directory’administration.
Ouvrez un navigateur et accédez au Centre d’administration Azure Active Directory. Connectez-vous à l’aide d’un compte personnel (compte Microsoft) ou d’un compte professionnel ou scolaire.
Sélectionnez Azure Active Directory dans le volet de navigation gauche, puis sélectionnez Inscriptions d’applications sous Gérer.
Notes
Les utilisateurs Azure AD B2C peuvent uniquement voir les inscriptions d’applications (héritées). Dans ce cas, consultez directement https://aka.ms/appregistrations .
Sélectionnez Nouvelle inscription. Sur la page Inscrire une application, définissez les valeurs comme suit.
- Définissez le Nom sur
React Graph Tutorial
. - Définissez les Types de comptes pris en charge sur Comptes dans un annuaire organisationnel et comptes personnels Microsoft.
- Sous URI de redirection, définissez la première flèche déroulante sur
Single-page application (SPA)
, et la valeur surhttp://localhost:3000
.
- Définissez le Nom sur
Choisissez Inscrire. Dans la page React Graph didacticiel, copiez la valeur de l’ID de l’application (client) et enregistrez-la, vous en aurez besoin à l’étape suivante.
Ajouter une authentification Azure AD
Dans cet exercice, vous allez étendre l’application de l’exercice précédent pour prendre en charge l’authentification avec Azure AD. Cette étape est nécessaire pour obtenir le jeton d’accès OAuth nécessaire pour appeler l’Graph Microsoft. Dans cette étape, vous allez intégrer la bibliothèque bibliothèque d’authentification Microsoft dans l’application.
Créez un fichier dans le répertoire ./src nommé Config.ts et ajoutez le code suivant.
export const config = { appId: 'YOUR_APP_ID_HERE', redirectUri: 'http://localhost:3000', scopes: [ 'user.read', 'mailboxsettings.read', 'calendars.readwrite' ] };
YOUR_APP_ID_HERE
Remplacez-le par l’ID de l’application à partir du portail d’inscription des applications.Important
Si vous utilisez un contrôle source tel que Git, il est temps d’exclure le fichier du contrôle source afin d’éviter toute fuite accidentelle de votre
Config.ts
ID d’application.
Implémentation de la connexion
Dans cette section, vous allez implémenter un fournisseur d’authentification, une sign-in et une sign-out.
Ouvrez ./src/index.tsx et ajoutez les
import
instructions suivantes en haut du fichier.import { PublicClientApplication, EventType, EventMessage, AuthenticationResult } from '@azure/msal-browser'; import config from './Config';
Ajoutez le code suivant avant la
ReactDOM.render
ligne.Ce code crée une instance de l’objet de la bibliothèque MSAL, recherche les comptes mis en cache et inscrit un rappel pour définir le compte actif après une connexion
PublicClientApplication
réussie.Mettez à
App
jour l’élémentReactDOM.render
dans l’appel pour transmettremsalInstance
la propriété nomméepca
.Ouvrez ./src/App.tsx et ajoutez le code suivant après la dernière
import
instruction.Remplacez la fonction
App
existante par ce qui suit.export default function App({ pca }: AppProps) { return( <MsalProvider instance={ pca }> <ProvideAppContext> <Router> <div> <NavBar /> <Container> <ErrorMessage /> <Route exact path="/" render={(props) => <Welcome {...props} /> } /> </Container> </div> </Router> </ProvideAppContext> </MsalProvider> ); }
Cela encapsule tous les autres éléments avec l’élément, rendant l’état
MsalProvider
d’authentification et l’acquisition de jeton disponibles.Ouvrez ./src/AppContext.tsx et ajoutez l’instruction suivante en
import
haut du fichier.import config from './Config';
Ajoutez la ligne suivante en haut de la
useProvideAppContext
fonction.const msal = useMsal();
Remplacez
const authProvider = undefined;
la ligne par ce qui suit.Remplacez la fonction
signIn
existante par ce qui suit.const signIn = async () => { const result = await msal.instance.loginPopup({ scopes: config.scopes, prompt: 'select_account' }); // TEMPORARY: Show the access token displayError('Access token retrieved', result.accessToken); };
Enregistrez vos modifications et actualisez le navigateur. Cliquez sur le bouton de connectez-vous et vous devriez voir une fenêtre int er qui se
https://login.microsoftonline.com
charge. Connectez-vous avec votre compte Microsoft et consentez aux autorisations demandées. La page de l’application doit s’actualiser et afficher le jeton.
Obtenir les détails de l’utilisateur
Dans cette section, vous allez modifier la fonction pour obtenir les détails de l’utilisateur auprès de signIn
Microsoft Graph.
Créez un fichier dans le répertoire ./src nommé GraphService.ts et ajoutez le code suivant.
Cela implémente la fonction, qui initialise le client Microsoft Graph avec le fourni et obtient le
getUser
AuthProvider
profil de l’utilisateur.Ouvrez ./src/AppContext.tsx et ajoutez l’instruction suivante en
import
haut du fichier.import { getUser } from './GraphService';
Remplacez la fonction
signIn
existante par le code suivant.Remplacez la fonction
signOut
existante par ce qui suit.Ajoutez
useEffect
l’appel suivant à l’intérieur.useProvideAppContext
Enregistrez vos modifications et démarrez l’application, une fois que vous vous êtes inscrit, vous devez revenir sur la page d’accueil, mais l’interface utilisateur doit changer pour indiquer que vous êtes connecté.
Cliquez sur l’avatar de l’utilisateur dans le coin supérieur droit pour accéder au lien de connexion. Le fait de cliquer sur Se déconnecter réinitialise la session et vous ramène à la page d’accueil.
Stockage et actualisation des jetons
À ce stade, votre application dispose d’un jeton d’accès, qui est envoyé dans l’en-tête des Authorization
appels d’API. Il s’agit du jeton qui permet à l’application d’accéder au Graph Microsoft au nom de l’utilisateur.
Cependant, ce jeton est de courte durée. Le jeton expire une heure après son émission. C’est là que le jeton d’actualisation devient utile. Le jeton d’actualisation permet à l’application de demander un nouveau jeton d’accès sans obliger l’utilisateur à se reconnecter.
Étant donné que l’application utilise la bibliothèque MSAL, vous n’avez pas besoin d’implémenter de logique de stockage ou d’actualisation de jeton. Le PublicClientApplication
jeton est mis en cache dans la session du navigateur. La méthode vérifie d’abord le jeton mis en cache et, s’il acquireTokenSilent
n’a pas expiré, elle le renvoie. S’il a expiré, il utilise le jeton d’actualisation mis en cache pour en obtenir un nouveau. Vous utiliserez davantage cette méthode dans le module suivant.
Obtenir un affichage Calendrier
Dans cet exercice, vous allez incorporer le Graph Microsoft dans l’application. Pour cette application, vous allez utiliser la bibliothèque cliente microsoft-graph pour appeler Microsoft Graph.
Récupérer les événements de calendrier à partir d’Outlook
Ouvrez ./src/GraphService.ts et ajoutez la fonction suivante.
export async function getUserWeekCalendar(accessToken: string, timeZone: string, startDate: Moment): Promise<Event[]> { const client = getAuthenticatedClient(accessToken); // Generate startDateTime and endDateTime query params // to display a 7-day window var startDateTime = startDate.format(); var endDateTime = moment(startDate).add(7, 'day').format(); // GET /me/calendarview?startDateTime=''&endDateTime='' // &$select=subject,organizer,start,end // &$orderby=start/dateTime // &$top=50 var response: PageCollection = await client .api('/me/calendarview') .header('Prefer', `outlook.timezone="${timeZone}"`) .query({ startDateTime: startDateTime, endDateTime: endDateTime }) .select('subject,organizer,start,end') .orderby('start/dateTime') .top(25) .get(); if (response["@odata.nextLink"]) { // Presence of the nextLink property indicates more results are available // Use a page iterator to get all results var events: Event[] = []; // Must include the time zone header in page // requests too var options: GraphRequestOptions = { headers: { 'Prefer': `outlook.timezone="${timeZone}"` } }; var pageIterator = new PageIterator(client, response, (event) => { events.push(event); return true; }, options); await pageIterator.iterate(); return events; } else { return response.value; } }
Que fait ce code ?
- L’URL qui sera appelée est
/me/calendarview
. - La
header
méthode ajoute l’en-têtePrefer: outlook.timezone=""
à la demande, ce qui entraîne la place des heures dans la réponse dans le fuseau horaire préféré de l’utilisateur. - La
query
méthode ajoute les paramètresstartDateTime
endDateTime
et définit la fenêtre de temps pour l’affichage Calendrier. - La
select
méthode limite les champs renvoyés pour chaque événement à ceux que l’affichage utilisera réellement. - La
orderby
méthode trie les résultats par date et heure de création, l’élément le plus récent étant le premier. - La
top
méthode limite les résultats d’une seule page à 25 événements. - Si la réponse contient une
@odata.nextLink
valeur, indiquant que d’autres résultats sont disponibles,PageIterator
un objet est utilisé pour passer en page dans la collection afin d’obtenir tous les résultats.
- L’URL qui sera appelée est
Créez un React pour afficher les résultats de l’appel. Créez un fichier dans le répertoire ./src nommé Calendar.tsx et ajoutez le code suivant.
import { useEffect, useState } from 'react'; import { NavLink as RouterNavLink, RouteComponentProps } from 'react-router-dom'; import { Table } from 'react-bootstrap'; import { findIana } from "windows-iana"; import { Event } from 'microsoft-graph'; import { getUserWeekCalendar } from './GraphService'; import { useAppContext } from './AppContext'; import { AuthenticatedTemplate } from '@azure/msal-react'; import { add, format, getDay, parseISO } from 'date-fns'; import { endOfWeek, startOfWeek } from 'date-fns/esm'; export default function Calendar(props: RouteComponentProps) { const app = useAppContext(); const [events, setEvents] = useState<Event[]>(); useEffect(() => { const loadEvents = async() => { if (app.user && !events) { try { const ianaTimeZones = findIana(app.user?.timeZone!); const events = await getUserWeekCalendar(app.authProvider!, ianaTimeZones[0].valueOf()); setEvents(events); } catch (err) { app.displayError!(err.message); } } }; loadEvents(); }); return ( <AuthenticatedTemplate> <pre><code>{JSON.stringify(events, null, 2)}</code></pre> </AuthenticatedTemplate> ); }
Pour l’instant, cela restituera simplement le tableau des événements dans JSON sur la page.
Ajoutez ce nouveau composant à l’application.
./src/App.tsx
Ouvrez et ajoutez l’instructionimport
suivante en haut du fichier.import Calendar from './Calendar';
Ajoutez le composant suivant juste après le composant existant
<Route>
.<Route exact path="/calendar" render={(props) => <Calendar {...props} /> } />
Enregistrez vos modifications, puis redémarrez l’application. Connectez-vous et cliquez sur le lien Calendrier dans la barre de navigation. Si tout fonctionne, vous devriez voir une image mémoire JSON des événements dans le calendrier de l’utilisateur.
Afficher les résultats
Vous pouvez maintenant mettre à jour le Calendar
composant pour afficher les événements de manière plus conviviale.
Créez un fichier dans le
./src
répertoire nomméCalendar.css
et ajoutez le code suivant..calendar-view-date-cell { width: 150px; } .calendar-view-date { width: 40px; font-size: 36px; line-height: 36px; margin-right: 10px; } .calendar-view-month { font-size: 0.75em; } .calendar-view-timespan { width: 200px; } .calendar-view-subject { font-size: 1.25em; } .calendar-view-organizer { font-size: .75em; }
Créez un React pour restituer les événements en une seule journée en tant que lignes de tableau. Créez un fichier dans le
./src
répertoire nomméCalendarDayRow.tsx
et ajoutez le code suivant.import React from 'react'; import moment, { Moment } from 'moment'; import { Event } from 'microsoft-graph'; interface CalendarDayRowProps { date: Moment | undefined; timeFormat: string; events: Event[]; } interface FormatMap { [key: string] : string; } // moment.js format strings are slightly // different than the ones returned by Graph const formatMap: FormatMap = { "h:mm tt": "h:mm A", "hh:mm tt": "hh:mm A" }; // Helper function to format Graph date/time in the user's // preferred format function formatDateTime(dateTime: string | undefined, format: string) { if (dateTime !== undefined) { return moment(dateTime).format(formatMap[format] || format); } } export default class CalendarDayRow extends React.Component<CalendarDayRowProps> { render() { var today = moment(); var rowClass = today.day() === this.props.date?.day() ? 'table-warning' : ''; var timeFormat = this.props.timeFormat; var dateCell = ( <td className='calendar-view-date-cell' rowSpan={this.props.events.length <= 0 ? 1 : this.props.events.length}> <div className='calendar-view-date float-left text-right'>{this.props.date?.format('DD')}</div> <div className='calendar-view-day'>{this.props.date?.format('dddd')}</div> <div className='calendar-view-month text-muted'>{this.props.date?.format('MMMM, YYYY')}</div> </td> ); if (this.props.events.length <= 0) { // Render an empty row for the day return ( <tr className={rowClass}> {dateCell} <td></td> <td></td> </tr> ); } return ( <React.Fragment> {this.props.events.map( function(event: Event, index: Number) { return ( <tr className={rowClass} key={event.id}> { index === 0 && dateCell } <td className="calendar-view-timespan"> <div>{formatDateTime(event.start?.dateTime, timeFormat)} - {formatDateTime(event.end?.dateTime, timeFormat)}</div> </td> <td> <div className="calendar-view-subject">{event.subject}</div> <div className="calendar-view-organizer">{event.organizer?.emailAddress?.name}</div> </td> </tr> ) } )} </React.Fragment> ) } }
Ajoutez les instructions
import
suivantes en haut de Calendar.tsx.import CalendarDayRow from './CalendarDayRow'; import './Calendar.css';
Remplacez l’instruction
return
existante par le code suivant.Cela divise les événements en jours respectifs et rend une section de tableau pour chaque jour.
Enregistrez les modifications et redémarrez l’application. Cliquez sur le lien Calendrier et l’application doit maintenant restituer une table des événements.
Créer un événement
Dans cette section, vous allez ajouter la possibilité de créer des événements sur le calendrier de l’utilisateur.
Ajouter une méthode à GraphService
Ouvrez ./src/GraphService.ts et ajoutez la fonction suivante pour créer un événement.
export async function createEvent(accessToken: string, newEvent: Event): Promise<Event> { const client = getAuthenticatedClient(accessToken); // POST /me/events // JSON representation of the new event is sent in the // request body return await client .api('/me/events') .post(newEvent); }
Créer un formulaire d’événement
Créez un fichier dans le répertoire ./src nommé NewEvent.tsx et ajoutez le code suivant.
import React from 'react'; import { NavLink as RouterNavLink, Redirect } from 'react-router-dom'; import { Button, Col, Form, FormGroup, Label, Input, Row } from 'reactstrap'; import { Attendee, Event } from 'microsoft-graph'; import { config } from './Config'; import withAuthProvider, { AuthComponentProps } from './AuthProvider'; import { createEvent } from './GraphService'; interface NewEventState { subject: string; attendees: string; start: string; end: string; body: string; disableCreate: boolean; redirect: boolean; } class NewEvent extends React.Component<AuthComponentProps, NewEventState> { constructor(props: any) { super(props); this.state = { subject: '', attendees: '', start: '', end: '', body: '', disableCreate: true, redirect: false } this.handleUpdate = this.handleUpdate.bind(this); this.isFormDisabled = this.isFormDisabled.bind(this); this.createEvent = this.createEvent.bind(this); } // Called whenever an input is changed handleUpdate(event: React.ChangeEvent<HTMLInputElement>) { // Set the state value that maps to the input var newState: any = { [event.target.name]: event.target.value }; this.setState(newState); } // Determines if form is ready to submit // Requires a subject, start, and end isFormDisabled(): boolean { return this.state.subject.length === 0 || this.state.start.length === 0 || this.state.end.length === 0; } // Creates the event when user clicks Create async createEvent() { // Get the value of attendees and split into an array var attendeeEmails = this.state.attendees.split(';'); var attendees: Attendee[] = []; // Create an Attendee object for each email address attendeeEmails.forEach((email) => { if (email.length > 0) { attendees.push({ emailAddress: { address: email } }); } }); // Create the Event object var newEvent: Event = { subject: this.state.subject, // Only add if there are attendees attendees: attendees.length > 0 ? attendees : undefined, // Specify the user's time zone so // the start and end are set correctly start: { dateTime: this.state.start, timeZone: this.props.user.timeZone }, end: { dateTime: this.state.end, timeZone: this.props.user.timeZone }, // Only add if a body was given body: this.state.body.length > 0 ? { contentType: "text", content: this.state.body } : undefined } try { // Get the user's access token var accessToken = await this.props.getAccessToken(config.scopes); // Create the event await createEvent(accessToken, newEvent); // Redirect to the calendar view this.setState({ redirect: true }); } catch (err) { this.props.setError('ERROR', JSON.stringify(err)); } } render() { if (this.state.redirect) { return <Redirect to="/calendar" /> } return ( <Form> <FormGroup> <Label for="subject">Subject</Label> <Input type="text" name="subject" id="subject" value={this.state.subject} onChange={this.handleUpdate} /> </FormGroup> <FormGroup> <Label for="attendees">Attendees</Label> <Input type="text" name="attendees" id="attendees" placeholder="Enter a list of email addresses, seperated by a semi-colon" value={this.state.attendees} onChange={this.handleUpdate} /> </FormGroup> <Row form> <Col> <FormGroup> <Label for="start">Start</Label> <Input type="datetime-local" name="start" id="start" value={this.state.start} onChange={this.handleUpdate} /> </FormGroup> </Col> <Col> <FormGroup> <Label for="end">End</Label> <Input type="datetime-local" name="end" id="end" value={this.state.end} onChange={this.handleUpdate} /> </FormGroup> </Col> </Row> <FormGroup> <Label for="body">Body</Label> <Input type="textarea" name="body" id="body" value={this.state.body} onChange={this.handleUpdate} /> </FormGroup> <Button color="primary" className="mr-2" disabled={this.isFormDisabled()} onClick={this.createEvent}>Create</Button> <RouterNavLink to="/calendar" className="btn btn-secondary" exact>Cancel</RouterNavLink> </Form> ) } } export default withAuthProvider(NewEvent);
Ouvrez ./src/App.tsx et ajoutez l’instruction
import
suivante en haut du fichier.import NewEvent from './NewEvent';
Ajoutez un nouvel itinéraire au nouveau formulaire d’événement. Ajoutez le code suivant juste après les autres
Route
éléments.<Route exact path="/newevent" render={(props) => <NewEvent {...props} /> } />
L’instruction
return
complète doit maintenant ressembler à ceci.Actualisez l’application et accédez à l’affichage Calendrier. Cliquez sur le bouton Nouvel événement. Remplissez les champs, puis cliquez sur Créer.
Félicitations !
Vous avez terminé le didacticiel React Microsoft Graph. Maintenant que vous disposez d’une application de travail qui appelle Microsoft Graph, vous pouvez expérimenter et ajouter de nouvelles fonctionnalités. Consultez la vue d’ensemble de Microsoft Graph pour voir toutes les données accessibles avec Microsoft Graph.
Commentaires
N’hésitez pas à nous faire part de vos commentaires sur ce didacticiel dans GitHub référentiel.
Vous avez un problème avec cette section ? Si c'est le cas, faites-nous part de vos commentaires pour que nous puissions l'améliorer.