Criar aplicativos de página única do React com o Microsoft Graph
Este tutorial ensina como criar um aplicativo React página única que usa a API do Microsoft Graph para recuperar informações de calendário para um usuário.
Dica
Se você preferir apenas baixar o tutorial concluído, poderá baixar ou clonar o GitHub repositório.
Pré-requisitos
Antes de iniciar este tutorial, você deve terNode.js e o Yarn instalados em sua máquina de desenvolvimento. Se você não tiver Node.js ou Yarn, visite os links anteriores para opções de download.
Você também deve ter uma conta pessoal da Microsoft com uma caixa de correio em Outlook.com, ou uma conta de trabalho ou de estudante da Microsoft. Se você não tiver uma conta da Microsoft, há algumas opções para obter uma conta gratuita:
- Você pode se inscrever em uma nova conta pessoal da Microsoft.
- Você pode se inscrever no programa Microsoft 365 desenvolvedor para obter uma assinatura Microsoft 365 gratuita.
Observação
Este tutorial foi escrito com o Nó versão 14.15.0 e o Yarn versão 1.22.10. As etapas neste guia podem funcionar com outras versões, mas que não foram testadas.
Comentários
Forneça qualquer comentário sobre este tutorial no repositório GitHub.
Criar um aplicativo de página única do React
Nesta seção, você criará um novo React app.
Abra sua interface de linha de comando (CLI), navegue até um diretório no qual você tem direitos para criar arquivos e execute os comandos a seguir para criar um novo React app.
yarn create react-app graph-tutorial --template typescript
Depois que o comando terminar, altere para o diretório '** do tutorial de gráfico em sua CLI e execute o seguinte comando para iniciar um servidor Web local.
yarn start
Observação
Se você não tiver o Yarn instalado, poderá
npm start
usá-lo.
Seu navegador padrão é aberto https://localhost:3000/ com uma página React padrão. Se o navegador não abrir, abra-o e navegue até verificar https://localhost:3000/ se o novo aplicativo funciona.
Adicionar pacotes de nó
Antes de continuar, instale alguns pacotes adicionais que você usará posteriormente:
- react-router-dom para roteamento declarativo dentro do React app.
- bootstrap para estilo e componentes comuns.
- react-bootstrap para React com base em Bootstrap.
- date-fns para formatação de datas e horas.
- windows-iana para traduzir Windows fusos horário para o formato IANA.
- msal-react for authenticating to Azure Active Directory and retrieving access tokens.
- microsoft-graph-client para fazer chamadas para o Microsoft Graph.
Execute o seguinte comando em sua 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
Design do aplicativo
Comece criando um contexto para o aplicativo.
Crie um novo arquivo no diretório ./src chamado AppContext.tsx e adicione as instruções
import
a seguir.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';
Adicione o código a seguir.
Adicione a seguinte função no final 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 }; }
Você concluirá a implementação desse contexto em seções posteriores.
Crie uma barra de navbar para o aplicativo. Crie um novo arquivo no
./src
diretório nomeado e adicione o código aNavBar.tsx
seguir.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> ); } }
Crie uma home page para o aplicativo. Crie um novo arquivo no
./src
diretório nomeado e adicione o código aWelcome.tsx
seguir.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> ); } }
Crie uma exibição de mensagem de erro para exibir mensagens para o usuário. Crie um novo arquivo no
./src
diretório nomeado e adicione o código aErrorMessage.tsx
seguir.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> ); } }
Abra o arquivo
./src/index.css
e substitua o conteúdo inteiro pelo seguinte:body { padding-top: 4.5rem; } .alert-pre { word-wrap: break-word; word-break: break-all; white-space: pre-wrap; }
Abra
./src/App.tsx
e substitua todo o conteúdo pelo seguinte.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> ); }
Adicione um arquivo de imagem de sua escolha no-profile-photo.png no diretório ./public/images. Essa imagem será usada como a foto do usuário quando o usuário não tiver nenhuma foto no Microsoft Graph.
Salve todas as suas alterações e reinicie o aplicativo. Agora, o aplicativo deve ter uma aparência muito diferente.
Registrar o aplicativo no portal
Neste exercício, você criará um novo registro de aplicativo Web do Azure AD usando o Azure Active Directory de administração.
Abra um navegador e navegue até o centro de administração do Azure Active Directory. Faça logon usando uma conta pessoal (também conhecida como Conta da Microsoft) ou Conta Corporativa ou de Estudante.
Selecione Azure Active Directory na navegação esquerda e selecione Registros de aplicativos em Gerenciar.
Observação
Os usuários do Azure AD B2C só podem ver registros de aplicativos (herdados). Nesse caso, vá diretamente para https://aka.ms/appregistrations .
Selecione Novo registro. Na página Registrar um aplicativo, defina os valores da seguinte forma.
- Defina Nome para
React Graph Tutorial
. - Defina Tipos de conta com suporte para Contas em qualquer diretório organizacional e contas pessoais da Microsoft.
- Em URI de Redirecionamento, defina o primeiro menu suspenso para
Single-page application (SPA)
e defina o valor comohttp://localhost:3000
.
- Defina Nome para
Escolha Registrar. Na página React Graph Tutorial, copie o valor da ID do Aplicativo (cliente) e salve-a, você precisará dela na próxima etapa.
Adicionar autenticação do Azure AD
Neste exercício, você estenderá o aplicativo do exercício anterior para dar suporte à autenticação com o Azure AD. Isso é necessário para obter o token de acesso OAuth necessário para chamar o microsoft Graph. Nesta etapa, você integrará a biblioteca da Biblioteca de Autenticação da Microsoft ao aplicativo.
Crie um novo arquivo no diretório ./src chamado Config.ts e adicione o código a seguir.
export const config = { appId: 'YOUR_APP_ID_HERE', redirectUri: 'http://localhost:3000', scopes: [ 'user.read', 'mailboxsettings.read', 'calendars.readwrite' ] };
Substitua
YOUR_APP_ID_HERE
pela ID do aplicativo no Portal de Registro de Aplicativos.Importante
Se você estiver usando o controle de origem, como git, agora seria um bom momento para excluir o arquivo do controle de origem para evitar o vazamento
Config.ts
inadvertida da ID do aplicativo.
Implementar login
Nesta seção, você implementará um provedor de autenticação, uma assinatura e uma saída.
Abra ./src/index.tsx e adicione as instruções a seguir
import
na parte superior do arquivo.import { PublicClientApplication, EventType, EventMessage, AuthenticationResult } from '@azure/msal-browser'; import config from './Config';
Adicione o código a seguir antes da
ReactDOM.render
linha.Esse código cria uma instância do objeto da biblioteca MSAL, verifica todas as contas armazenadas em cache e registra um retorno de chamada para definir a conta ativa após um
PublicClientApplication
logon bem-sucedido.Atualize
App
o elemento na chamada para passar o em uma propriedade chamadaReactDOM.render
msalInstance
pca
.Abra ./src/App.tsx e adicione o código a seguir após a última
import
instrução.Substitua a função
App
existente pela seguinte.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> ); }
Isso envolve todos os outros elementos com o elemento, disponibilizando o estado de autenticação e
MsalProvider
a aquisição de token.Abra ./src/AppContext.tsx e adicione a seguinte instrução
import
na parte superior do arquivo.import config from './Config';
Adicione a seguinte linha na parte superior da
useProvideAppContext
função.const msal = useMsal();
Substitua a
const authProvider = undefined;
linha pelo seguinte.Substitua a função
signIn
existente pela seguinte.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); };
Salve suas alterações e atualize o navegador. Clique no botão entrar e você deve ver uma janela pop-up que carrega
https://login.microsoftonline.com
. Faça logon com sua conta da Microsoft e consenta com as permissões solicitadas. A página do aplicativo deve ser atualizada, mostrando o token.
Obter detalhes do usuário
Nesta seção, você modificará a função para obter os detalhes do usuário do signIn
Microsoft Graph.
Crie um novo arquivo no diretório ./src chamado GraphService.ts e adicione o código a seguir.
Isso implementa a função, que inicializa o cliente Graph Microsoft com o
getUser
AuthProvider
fornecido e obtém o perfil do usuário.Abra ./src/AppContext.tsx e adicione a seguinte instrução
import
na parte superior do arquivo.import { getUser } from './GraphService';
Substitua a função
signIn
existente pelo código seguinte.Substitua a função
signOut
existente pela seguinte.Adicione a chamada
useEffect
a seguir dentrouseProvideAppContext
.Salve suas alterações e inicie o aplicativo, depois de entrar, você deve terminar de volta na home page, mas a interface do usuário deve mudar para indicar que você está in-loco.
Clique no avatar do usuário no canto superior direito para acessar o link Sair. Clicar em Sair redefine a sessão e retorna você para a home page.
Armazenar e atualizar tokens
Neste ponto, seu aplicativo tem um token de acesso, que é enviado no Authorization
header de chamadas da API. Esse é o token que permite que o aplicativo acesse o microsoft Graph em nome do usuário.
No entanto, esse token tem vida curta. O token expira uma hora após a emissão. É aqui que o token de atualização se torna útil. O token de atualização permite que o aplicativo solicite um novo token de acesso sem exigir que o usuário faça login novamente.
Como o aplicativo está usando a biblioteca MSAL, você não precisa implementar nenhum armazenamento de token ou lógica de atualização. O PublicClientApplication
cache do token na sessão do navegador. O método primeiro verifica o token armazenado em acquireTokenSilent
cache e, se não estiver expirado, ele o retornará. Se expirar, ele usará o token de atualização em cache para obter um novo. Você usará mais esse método no módulo a seguir.
Obter uma exibição de calendário
Neste exercício, você incorporará o microsoft Graph no aplicativo. Para esse aplicativo, você usará a biblioteca microsoft-graph-client para fazer chamadas para o Microsoft Graph.
Obtenha eventos de calendário do Outlook
Abra ./src/GraphService.ts e adicione a seguinte função.
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; } }
Considere o que este código está fazendo.
- O URL que será chamado é
/me/calendarview
. - O
header
método adiciona oPrefer: outlook.timezone=""
header à solicitação, fazendo com que os horários na resposta sejam no fuso horário preferencial do usuário. - O
query
método adiciona osstartDateTime
parâmetros eendDateTime
, definindo a janela de tempo para o modo de exibição de calendário. - O
select
método limita os campos retornados para cada evento para apenas aqueles que o modo de exibição realmente usará. - O
orderby
método classifica os resultados pela data e hora em que foram criados, sendo o item mais recente o primeiro. - O
top
método limita os resultados em uma única página a 25 eventos. - Se a resposta contiver
@odata.nextLink
um valor, indicando que há mais resultados disponíveis,PageIterator
um objeto será usado para páginar pela coleção para obter todos os resultados.
- O URL que será chamado é
Crie um React para exibir os resultados da chamada. Crie um novo arquivo no diretório ./src chamado Calendar.tsx e adicione o código a seguir.
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> ); }
Por enquanto, isso apenas renderiza a matriz de eventos no JSON na página.
Adicione esse novo componente ao aplicativo. Abra
./src/App.tsx
e adicione a instruçãoimport
a seguir à parte superior do arquivo.import Calendar from './Calendar';
Adicione o componente a seguir logo após o
<Route>
.<Route exact path="/calendar" render={(props) => <Calendar {...props} /> } />
Salve suas alterações e reinicie o aplicativo. Entre e clique no link Calendário na barra de nav. Se tudo funcionar, você deverá ver um despejo JSON de eventos no calendário do usuário.
Exibir os resultados
Agora você pode atualizar o componente Calendar
para exibir os eventos de maneira mais fácil de usar.
Crie um novo arquivo no diretório
./src
nomeadoCalendar.css
e adicione o código a seguir..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; }
Crie um React para renderizar eventos em um único dia como linhas de tabela. Crie um novo arquivo no diretório
./src
nomeadoCalendarDayRow.tsx
e adicione o código a seguir.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> ) } }
Adicione as instruções
import
a seguir à parte superior de Calendar.tsx.import CalendarDayRow from './CalendarDayRow'; import './Calendar.css';
Substitua a instrução existente
return
pelo código a seguir.Isso divide os eventos em seus respectivos dias e renderiza uma seção de tabela para cada dia.
Salve as alterações e reinicie o aplicativo. Clique no link Calendário e o aplicativo deve renderizar uma tabela de eventos.
Criar um novo evento
Nesta seção, você adicionará a capacidade de criar eventos no calendário do usuário.
Adicionar método ao GraphService
Abra ./src/GraphService.ts e adicione a seguinte função para criar um novo evento.
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); }
Criar novo formulário de evento
Crie um novo arquivo no diretório ./src chamado NewEvent.tsx e adicione o código a seguir.
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);
Abra ./src/App.tsx e adicione a seguinte
import
instrução à parte superior do arquivo.import NewEvent from './NewEvent';
Adicione uma nova rota ao novo formulário de evento. Adicione o código a seguir logo após os outros
Route
elementos.<Route exact path="/newevent" render={(props) => <NewEvent {...props} /> } />
A instrução
return
completa agora deve ter esta aparência.Atualize o aplicativo e navegue até o visualização de calendário. Clique no botão Novo evento . Preencha os campos e clique em Criar.
Parabéns!
Você concluiu o tutorial React microsoft Graph. Agora que você tem um aplicativo de trabalho que chama a Microsoft Graph, você pode experimentar e adicionar novos recursos. Visite a visão geral do microsoft Graph para ver todos os dados que você pode acessar com o Microsoft Graph.
Comentários
Forneça qualquer comentário sobre este tutorial no repositório GitHub .
Tem algum problema com essa seção? Se tiver, envie seus comentários para que possamos melhorar esta seção.