Mettre à jour l’application pour créer et répertorier des conteneurs Incorporés SharePoint
Dans cet exercice, vous allez mettre à jour le projet existant pour créer et récupérer des conteneurs SharePoint Embedded.
Ajouter des fonctionnalités de connexion au spa React front-end
Commençons par ajouter la prise en charge de la connexion utilisateur au projet frontal React SPA. Cela implique l’ajout d’un code de configuration pour la bibliothèque d’authentification Microsoft (MSAL) et la configuration du Kit de ressources Microsoft Graph avec les détails de connexion nécessaires.
Configurer le fournisseur d’authentification
Recherchez et ouvrez le fichier ./src/index.tsx .
Ajoutez les importations suivantes après les importations existantes :
import { Providers } from "@microsoft/mgt-element";
import { Msal2Provider } from "@microsoft/mgt-msal2-provider";
import * as Constants from "./common/constants"
import * as Scopes from "./common/scopes";
Enfin, ajoutez le code suivant avant le code de rendu React pour configurer un fournisseur MSAL global pour le Kit de ressources Microsoft Graph :
Providers.globalProvider = new Msal2Provider({
clientId: Constants.CLIENT_ENTRA_APP_CLIENT_ID,
authority: Constants.CLIENT_ENTRA_APP_AUTHORITY,
scopes: [
...Scopes.GRAPH_OPENID_CONNECT_BASIC,
Scopes.GRAPH_USER_READ_ALL,
Scopes.GRAPH_FILES_READ_WRITE_ALL,
Scopes.GRAPH_SITES_READ_ALL,
Scopes.SPEMBEDDED_FILESTORAGECONTAINER_SELECTED
]
});
Mettre à jour la page d’accueil de l’application pour gérer le processus de connexion et de déconnexion
Recherchez et ouvrez le fichier ./src/App.tsx . Supprimez l’importation du logo.svg
fichier, puis ajoutez et mettez à jour les importations restantes pour refléter le code suivant :
import React, {
useState, useEffect
} from "react";
import {
Providers,
ProviderState
} from "@microsoft/mgt-element";
import { Login } from "@microsoft/mgt-react";
import {
FluentProvider,
Text,
webLightTheme
} from "@fluentui/react-components"
import './App.css';
import {
InteractionRequiredAuthError,
PublicClientApplication
} from "@azure/msal-browser";
import * as Scopes from "./common/scopes";
import * as Constants from "./common/constants";
Après les instructions d’importation, ajoutez le hook React personnalisé suivant pour obtenir l’état de connexion de l’utilisateur actuel :
function useIsSignedIn() {
const [isSignedIn, setIsSignedIn] = useState(false);
useEffect(() => {
const updateState = async () => {
const provider = Providers.globalProvider;
setIsSignedIn(provider && provider.state === ProviderState.SignedIn);
};
Providers.onProviderUpdated(updateState);
updateState();
return () => {
Providers.removeProviderUpdatedListener(updateState);
}
}, []);
return isSignedIn;
}
Maintenant, mettez à jour en App
ajoutant le code suivant après la déclaration :
const isSignedIn = useIsSignedIn();
const promptForContainerConsent = async (event: CustomEvent<undefined>): Promise<void> => {
const containerScopes = {
scopes: [Scopes.SPEMBEDDED_FILESTORAGECONTAINER_SELECTED],
redirectUri: `${window.location.protocol}://${window.location.hostname}${(window.location.port === '80' || window.location.port === '443') ? '' : ':' + window.location.port}`
};
const msalInstance = new PublicClientApplication({
auth: {
clientId: Constants.CLIENT_ENTRA_APP_CLIENT_ID,
authority: Constants.CLIENT_ENTRA_APP_AUTHORITY,
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: false,
},
});
msalInstance.acquireTokenSilent(containerScopes)
.then(response => {
console.log('tokenResponse', JSON.stringify(response));
})
.catch(async (error) => {
if (error instanceof InteractionRequiredAuthError) {
return msalInstance.acquireTokenPopup(containerScopes);
}
});
}
Ce code obtient d’abord l’état de connexion actuel de l’utilisateur, puis configure et obtient un jeton d’accès une fois que l’utilisateur sélectionne un bouton dans le rendu.
Enfin, mettez à jour le rendu du composant en remplaçant l’instruction du return()
composant par ce qui suit :
return (
<FluentProvider theme={webLightTheme}>
<div className="App">
<Text size={900} weight='bold'>Sample SPA SharePoint Embedded App</Text>
<Login loginCompleted={promptForContainerConsent} />
<div>
</div>
</div>
</FluentProvider>
);
Tester l’authentification pour l’application React
Nous allons maintenant tester l’application React côté client pour vérifier que l’authentification fonctionne.
À partir de la ligne de commande dans le dossier racine du projet, exécutez la commande suivante :
npm run start
Le script génère les projets côté serveur & côté client, les démarre et lance un navigateur sur le projet côté client :
Sélectionnez le bouton Se connecter et connectez-vous à l’aide du compte professionnel et scolaire avec un accès administrateur à votre locataire Microsoft 365.
Une fois connecté, vous êtes redirigé vers votre application React affichant le nom et l’adresse e-mail de l’utilisateur connecté :
Arrêtez le serveur en appuyant sur Ctrl + C dans la console.
Ajouter la possibilité de lister et sélectionner des conteneurs
Une fois le projet de base configuré pour prendre en charge l’authentification utilisateur, nous allons maintenant ajouter la prise en charge à la liste et à la sélection des conteneurs dans la partition de votre locataire.
La gestion des conteneurs est une opération privilégiée qui nécessite un jeton d’accès qui doit être obtenu côté serveur. Commençons par créer les parties d’API côté serveur pour prendre en charge l’application React.
Ajouter une méthode utilitaire pour récupérer un jeton OBO pour appeler Microsoft Graph
Nous avons d’abord besoin d’un fichier utilitaire pour obtenir un jeton à l’aide du flux OAuth2 On-Behalf-Of à l’aide de nos informations d’identification existantes.
Créez un fichier ./server/auth.ts et ajoutez-y le code suivant :
import { ConfidentialClientApplication } from "@azure/msal-node";
require('isomorphic-fetch');
import * as MSGraph from '@microsoft/microsoft-graph-client';
import * as Scopes from './common/scopes';
export const getGraphToken = async (confidentialClient: ConfidentialClientApplication, token: string): Promise<[boolean, string | any]> => {
try {
const graphTokenRequest = {
oboAssertion: token,
scopes: [
Scopes.GRAPH_SITES_READ_ALL,
Scopes.SPEMBEDDED_FILESTORAGECONTAINER_SELECTED
]
};
const oboGraphToken = (await confidentialClient.acquireTokenOnBehalfOf(graphTokenRequest))!.accessToken;
return [true, oboGraphToken];
} catch (error: any) {
const errorResult = {
status: 500,
body: JSON.stringify({
message: `Unable to generate Microsoft Graph OBO token: ${error.message}`,
providedToken: token
})
};
return [false, errorResult];
}
}
Cela prend un ConfidentialClientApplication configuré et le jeton d’ID de l’utilisateur, et utilise la bibliothèque MSAL pour demander un nouveau jeton que nous pouvons utiliser pour appeler Microsoft Graph.
Ajouter la gestion des conteneurs au projet d’API côté serveur
À présent, nous allons créer le gestionnaire pour obtenir une liste des conteneurs utilisant Microsoft Graph à renvoyer à notre application React. Créez un fichier ./server/listContainers.ts et ajoutez-y les importations suivantes :
import {
Request,
Response
} from "restify";
import * as MSAL from "@azure/msal-node";
require('isomorphic-fetch');
import * as MSGraph from '@microsoft/microsoft-graph-client';
import { getGraphToken } from "./auth";
Ensuite, ajoutez le code suivant pour créer une instance d’une MSAL ConfidentialClientApplication qui sera utilisée pour obtenir le jeton d’accès OBO :
const msalConfig: MSAL.Configuration = {
auth: {
clientId: process.env['API_ENTRA_APP_CLIENT_ID']!,
authority: process.env['API_ENTRA_APP_AUTHORITY']!,
clientSecret: process.env['API_ENTRA_APP_CLIENT_SECRET']!
},
system: {
loggerOptions: {
loggerCallback(loglevel: any, message: any, containsPii: any) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: MSAL.LogLevel.Verbose,
}
}
};
const confidentialClient = new MSAL.ConfidentialClientApplication(msalConfig);
Créez et exportez une fonction qui effectuera les opérations suivantes :
- Vérifiez que la requête inclut un
Authorization
en-tête avec un jeton d’accès. - Utilisez ce jeton et le
ConfidentialClientApplication
pour obtenir un jeton OBO que nous pouvons utiliser pour appeler Microsoft Graph. - Utilisez le jeton OBO pour créer un
AuthenticationProvider
client que nous allons utiliser pour appeler Microsoft Graph.
export const listContainers = async (req: Request, res: Response) => {
if (!req.headers.authorization) {
res.send(401, { message: 'No access token provided.' });
return;
}
const [bearer, token] = (req.headers.authorization || '').split(' ');
const [graphSuccess, oboGraphToken] = await getGraphToken(confidentialClient, token);
if (!graphSuccess) {
res.send(200, oboGraphToken);
return;
}
const authProvider = (callback: MSGraph.AuthProviderCallback) => {
callback(null, oboGraphToken);
};
}
La dernière étape consiste à créer le client Microsoft Graph et à demander tous les conteneurs qui ont un ensemble spécifique ContainerTypeId
. Ajoutez l’instantané de code suivant avant le crochet fermant de la fonction :
try {
const graphClient = MSGraph.Client.init({
authProvider: authProvider,
defaultVersion: 'beta'
});
const graphResponse = await graphClient.api(`storage/fileStorage/containers?$filter=containerTypeId eq ${process.env["CONTAINER_TYPE_ID"]}`).get();
res.send(200, graphResponse);
return;
} catch (error: any) {
res.send(500, { message: `Unable to list containers: ${error.message}` });
return;
}
Ajoutez ce nouveau point de terminaison à notre serveur restify. Recherchez et ouvrez le fichier ./server/index.ts , ajoutez une instruction d’importation unique à la fin des importations existantes et ajoutez un écouteur pour les requêtes HTTP GET au point de /api/listContainers
terminaison :
import { listContainers } from "./listContainers";
...
server.get('/api/listContainers', async (req, res, next) => {
try {
const response = await listContainers(req, res);
res.send(200, response)
} catch (error: any) {
res.send(500, { message: `Error in API server: ${error.message}` });
}
next();
});
Mettre à jour le projet React pour afficher nos conteneurs
Avec la configuration de l’API côté serveur, nous pouvons mettre à jour notre projet React pour fournir aux utilisateurs une interface permettant de sélectionner un conteneur existant ou de créer un conteneur.
Commencez par créer une interface, ./src/common/IContainer.ts, avec le contenu suivant pour représenter l’objet que nous allons envoyer et recevoir des appels Microsoft Graph :
export interface IContainer {
id: string;
displayName: string;
containerTypeId: string;
createdDateTime: string;
}
Créez un service qui sera utilisé pour appeler notre point de terminaison d’API ou passer des appels directs à partir de l’application React vers Microsoft Graph. Créez un fichier ./src/services/spembedded.ts et ajoutez-y le code suivant :
import { Providers, ProviderState } from '@microsoft/mgt-element';
import * as Msal from '@azure/msal-browser';
import * as Constants from './../common/constants';
import * as Scopes from './../common/scopes';
import { IContainer } from './../common/IContainer';
export default class SpEmbedded {
}
Ensuite, ajoutez une fonction utilitaire pour obtenir un jeton d’accès que nous pouvons utiliser pour appeler Microsoft Graph. Cela crée un MSAL PublicClientApplication
que nous utiliserons pour envoyer afin d’appeler notre API côté serveur. Ajoutez la fonction suivante à la classe SharePoint Embedded :
async getApiAccessToken() {
const msalConfig: Msal.Configuration = {
auth: {
clientId: Constants.CLIENT_ENTRA_APP_CLIENT_ID,
authority: Constants.CLIENT_ENTRA_APP_AUTHORITY,
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: false
}
};
const scopes: Msal.SilentRequest = {
scopes: [`api://${Constants.CLIENT_ENTRA_APP_CLIENT_ID}/${Scopes.SPEMBEDDED_CONTAINER_MANAGE}`],
prompt: 'select_account',
redirectUri: `${window.location.protocol}//${window.location.hostname}${(window.location.port === '80' || window.location.port === '443') ? '' : ':' + window.location.port}`
};
const publicClientApplication = new Msal.PublicClientApplication(msalConfig);
await publicClientApplication.initialize();
let tokenResponse;
try {
tokenResponse = await publicClientApplication.acquireTokenSilent(scopes);
return tokenResponse.accessToken;
} catch (error) {
if (error instanceof Msal.InteractionRequiredAuthError) {
tokenResponse = await publicClientApplication.acquireTokenPopup(scopes);
return tokenResponse.accessToken;
}
console.log(error)
return null;
}
};
Ajoutez la méthode suivante listContainers()
qui appellera notre API côté serveur pour obtenir la liste de tous nos conteneurs. Cela permet d’obtenir le jeton d’accès retourné par notre méthode utilitaire et de l’inclure dans les appels à l’API côté serveur. Rappelez-vous que ce jeton d’accès est utilisé pour créer un MSAL ConfidentialClientApplication
afin d’obtenir un jeton OBO pour appeler Microsoft Graph. Ce jeton OBO a plus d’autorisations qui lui sont accordées que nous ne pouvons obtenir qu’à partir d’un appel côté serveur :
async listContainers(): Promise<IContainer[] | undefined> {
const api_endpoint = `${Constants.API_SERVER_URL}/api/listContainers`;
if (Providers.globalProvider.state === ProviderState.SignedIn) {
const token = await this.getApiAccessToken();
const containerRequestHeaders = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
};
const containerRequestOptions = {
method: 'GET',
headers: containerRequestHeaders
};
const response = await fetch(api_endpoint, containerRequestOptions);
if (response.ok) {
const containerResponse = await response.json();
return (containerResponse.value)
? (containerResponse.value) as IContainer[]
: undefined;
} else {
console.error(`Unable to list Containers: ${JSON.stringify(response)}`);
return undefined;
}
}
};
À présent, créez un composant React qui gérera toutes nos tâches de conteneur et l’interface utilisateur. Créez un fichier , ./src/components/containers.tsx, puis ajoutez-y le code suivant :
import React, { useEffect, useState } from 'react';
import {
Button,
Dialog, DialogActions, DialogContent, DialogSurface, DialogBody, DialogTitle, DialogTrigger,
Dropdown, Option,
Input, InputProps, InputOnChangeData,
Label,
Spinner,
makeStyles, shorthands, useId
} from '@fluentui/react-components';
import type {
OptionOnSelectData,
SelectionEvents
} from '@fluentui/react-combobox'
import { IContainer } from "./../common/IContainer";
import SpEmbedded from '../services/spembedded';
const spe = new SpEmbedded();
const useStyles = makeStyles({
root: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
...shorthands.padding('25px'),
},
containerSelector: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
rowGap: '10px',
...shorthands.padding('25px'),
},
containerSelectorControls: {
width: '400px',
},
dialogContent: {
display: 'flex',
flexDirection: 'column',
rowGap: '10px',
marginBottom: '25px'
}
});
export const Containers = (props: any) => {
// BOOKMARK 1 - constants & hooks
// BOOKMARK 2 - handlers go here
// BOOKMARK 3 - component rendering
return (
);
}
export default Containers;
Remarque
Notez les // BOOKMARK #
commentaires dans le composant . Ceux-ci pour vous assurer que vous ajoutez du code aux emplacements appropriés.
La première étape consiste à obtenir la liste des conteneurs. Commencez par ajouter le code suivant avant // BOOKMARK 1
. Cela définit quelques valeurs d’état pour contenir les conteneurs récupérés à partir de notre API côté serveur :
const [containers, setContainers] = useState<IContainer[]>([]);
const [selectedContainer, setSelectedContainer] = useState<IContainer | undefined>(undefined);
const containerSelector = useId('containerSelector');
Ensuite, ajoutez le hook React suivant après // BOOKMARK 1
pour obtenir tous les conteneurs lors du chargement de la page et définir l’objet d’état qui en gardera le suivi :
useEffect(() => {
(async () => {
const containers = await spe.listContainers();
if (containers) {
setContainers(containers);
}
})();
}, []);
Créez un gestionnaire d’événements après l’implémentation du hook React que vous venez d’ajouter qui se déclenche lorsqu’un utilisateur sélectionne un conteneur dans le contrôle de liste déroulante que nous allons ajouter à notre expérience utilisateur :
const onContainerDropdownChange = (event: SelectionEvents, data: OptionOnSelectData) => {
const selected = containers.find((container) => container.id === data.optionValue);
setSelectedContainer(selected);
};
Mettez à jour le rendu en ajoutant ce qui suit à la return()
méthode après le // BOOKMARK 3
code. Cela crée un DropDown
contrôle et un espace réservé où nous allons ajouter une liste du contenu dans le conteneur sélectionné :
<div className={styles.root}>
<div className={styles.containerSelector}>
<Dropdown
id={containerSelector}
placeholder="Select a Storage Container"
className={styles.containerSelectorControls}
onOptionSelect={onContainerDropdownChange}>
{containers.map((option) => (
<Option key={option.id} value={option.id}>{option.displayName}</Option>
))}
</Dropdown>
</div>
{selectedContainer && (`[[TOOD]] container "${selectedContainer.displayName}" contents go here`)}
</div>
Ce code utilise un objet de style que nous avons ajouté au composant lors de sa création initiale. Pour utiliser les styles, ajoutez le code suivant juste avant l’instruction et // BOOKMARK 3
le return()
commentaire :
const styles = useStyles();
La dernière étape consiste à ajouter notre nouveau Containers
composant à l’application. Recherchez et ouvrez le ./src/App.tsx
fichier et ajoutez l’importation suivante après les importations existantes :
import Containers from "./components/containers";
Localisez le <div></div>
balisage dans le du return()
composant . Remplacez ce balisage par ce qui suit pour ajouter notre Containers
composant uniquement si l’utilisateur est connecté :
<div>
{isSignedIn && (<Containers />)}
</div>
Liste des tests et sélection des conteneurs
Nous allons maintenant tester l’application React côté client pour voir les effets de nos modifications de liste et d’affichage des conteneurs dans l’application React.
À partir de la ligne de commande dans le dossier racine du projet, exécutez la commande suivante :
npm run start
Lorsque le navigateur se charge, connectez-vous à l’aide du même compte professionnel et scolaire que celui que vous avez utilisé.
Après la connexion, la page se recharge et doit afficher une liste de conteneurs si vous en avez déjà créé un.
Lorsque vous sélectionnez un conteneur, notez que la logique conditionnelle affiche l’espace réservé avec le nom du conteneur sélectionné :
Arrêtez le serveur en appuyant sur Ctrl + C dans la console.
Ajouter la possibilité de créer de nouveaux conteneurs
Dans cette section, vous allez mettre à jour l’API côté serveur et l’application React pour créer des éléments à partir de notre application web.
Commençons par créer les parties d’API côté serveur pour prendre en charge l’application React.
Ajout de la prise en charge de la création de conteneurs dans le projet d’API côté serveur
À présent, nous allons créer le gestionnaire pour créer un conteneur à l’aide de Microsoft Graph à renvoyer à notre application React. Créez un fichier ./server/createContainer.ts et ajoutez-y les importations suivantes :
import {
Request,
Response
} from "restify";
import * as MSAL from "@azure/msal-node";
require('isomorphic-fetch');
import * as MSGraph from '@microsoft/microsoft-graph-client';
import { getGraphToken } from "./auth";
Ensuite, ajoutez le code suivant pour créer une instance d’un MSAL ConfidentialClientApplication
qui sera utilisé pour obtenir le jeton d’accès OBO :
const msalConfig: MSAL.Configuration = {
auth: {
clientId: process.env['API_ENTRA_APP_CLIENT_ID']!,
authority: process.env['API_ENTRA_APP_AUTHORITY']!,
clientSecret: process.env['API_ENTRA_APP_CLIENT_SECRET']!
},
system: {
loggerOptions: {
loggerCallback(loglevel: any, message: any, containsPii: any) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: MSAL.LogLevel.Verbose,
}
}
};
const confidentialClient = new MSAL.ConfidentialClientApplication(msalConfig);
Créez et exportez une fonction qui effectuera les opérations suivantes :
- Vérifiez que la requête inclut un
Authorization
en-tête avec un jeton d’accès. - Utilisez ce jeton et le
ConfidentialClientApplication
pour obtenir un jeton OBO que nous pouvons utiliser pour appeler Microsoft Graph. - Utilisez le jeton OBO pour créer un
AuthenticationProvider
client que nous allons utiliser pour appeler Microsoft Graph.
export const createContainer = async (req: Request, res: Response) => {
if (!req.headers.authorization) {
res.send(401, { message: 'No access token provided.' });
return;
}
const [bearer, token] = (req.headers.authorization || '').split(' ');
const [graphSuccess, graphTokenRequest] = await getGraphToken(confidentialClient, token);
if (!graphSuccess) {
res.send(200, graphTokenRequest);
return;
}
const authProvider = (callback: MSGraph.AuthProviderCallback) => {
callback(null, graphTokenRequest);
};
}
La dernière étape consiste à créer le client Microsoft Graph et à envoyer la demande de création d’un conteneur défini sur un spécifique ContainerTypeId
. Ajoutez l’instantané de code suivant avant le crochet fermant de la fonction :
try {
const graphClient = MSGraph.Client.init({
authProvider: authProvider,
defaultVersion: 'beta'
});
const containerRequestData = {
displayName: req.body!.displayName,
description: (req.body?.description) ? req.body.description : '',
containerTypeId: process.env["CONTAINER_TYPE_ID"]
};
const graphResponse = await graphClient.api(`storage/fileStorage/containers`).post(containerRequestData);
res.send(200, graphResponse);
return;
} catch (error: any) {
res.send(500, { message: `Failed to create container: ${error.message}` });
return;
}
Ajoutez ce nouveau point de terminaison à notre serveur restify. Recherchez et ouvrez le fichier ./server/index.ts , ajoutez une instruction d’importation unique à la fin des importations existantes et ajoutez un écouteur pour les requêtes HTTP POST au point de /api/createContainers
terminaison :
import { createContainer } from "./createContainer";
...
server.post('/api/createContainer', async (req, res, next) => {
try {
const response = await createContainer(req, res);
res.send(200, response)
} catch (error: any) {
res.send(500, { message: `Error in API server: ${error.message}` });
}
next();
});
Mettre à jour le projet React pour créer un conteneur
Recherchez et ouvrez le fichier ./src/services/spembedded.ts et ajoutez le code suivant à la classe :
async createContainer(containerName: string, containerDescription: string = ''): Promise<IContainer | undefined> {
const api_endpoint = `${Constants.API_SERVER_URL}/api/createContainer`;
if (Providers.globalProvider.state === ProviderState.SignedIn) {
const token = await this.getApiAccessToken();
const containerRequestHeaders = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
};
const containerRequestData = {
displayName: containerName,
description: containerDescription
};
const containerRequestOptions = {
method: 'POST',
headers: containerRequestHeaders,
body: JSON.stringify(containerRequestData)
};
const response = await fetch(api_endpoint, containerRequestOptions);
if (response.ok) {
const containerResponse = await response.json();
return containerResponse as IContainer;
} else {
console.error(`Unable to create container: ${JSON.stringify(response)}`);
return undefined;
}
}
};
Cette nouvelle méthode est similaire à la méthode existante listContainers()
, sauf qu’elle crée un objet et l’envoie en tant que POST à notre API côté serveur.
La dernière étape consiste à mettre à jour notre Containers
composant pour mettre à jour l’interface utilisateur afin de prendre en charge la création d’un conteneur. Recherchez et ouvrez le fichier ./src/components/containers.tsx .
Pour cette étape, nous allons utiliser un composant Fluent UI React Dialog
. Commencez par ajouter les objets d’état et d’ID de composant d’interface utilisateur suivants immédiatement avant le // BOOKMARK 1
commentaire :
const [dialogOpen, setDialogOpen] = useState(false);
const containerName = useId('containerName');
const [name, setName] = useState('');
const containerDescription = useId('containerDescription');
const [description, setDescription] = useState('');
const [creatingContainer, setCreatingContainer] = useState(false);
Ensuite, ajoutez le code suivant juste avant le // BOOKMARK 2
commentaire. Ces gestionnaires sont utilisés pour mettre à jour les propriétés de nom et de description du nouveau conteneur à partir des Input
composants qui se trouveront dans .Dialog
Ils sont également utilisés pour gérer avec l’utilisateur sélectionne un bouton pour créer le conteneur :
const handleNameChange: InputProps["onChange"] = (event: React.ChangeEvent<HTMLInputElement>, data: InputOnChangeData): void => {
setName(data?.value);
};
const handleDescriptionChange: InputProps["onChange"] = (event: React.ChangeEvent<HTMLInputElement>, data: InputOnChangeData): void => {
setDescription(data?.value);
};
const onContainerCreateClick = async (event: React.MouseEvent<HTMLButtonElement>): Promise<void> => {
setCreatingContainer(true);
const newContainer = await spe.createContainer(name, description);
if (newContainer) {
setName('');
setDescription('');
setContainers(current => [...current, newContainer]);
setSelectedContainer(newContainer);
setDialogOpen(false);
} else {
setName('');
setDescription('');
}
setCreatingContainer(false);
}
Enfin, ajoutez le code React suivant immédiatement après l’élément fermant </Dropdown>
. Cela crée un composant Fluent UI React Dialog
déclenché à partir d’un bouton :
<Dialog open={dialogOpen} onOpenChange={(event, data) => setDialogOpen(data.open)}>
<DialogTrigger disableButtonEnhancement>
<Button className={styles.containerSelectorControls} appearance='primary'>Create a new storage Container</Button>
</DialogTrigger>
<DialogSurface>
<DialogBody>
<DialogTitle>Create a new storage Container</DialogTitle>
<DialogContent className={styles.dialogContent}>
<Label htmlFor={containerName}>Container name:</Label>
<Input id={containerName} className={styles.containerSelectorControls} autoFocus required
value={name} onChange={handleNameChange}></Input>
<Label htmlFor={containerDescription}>Container description:</Label>
<Input id={containerDescription} className={styles.containerSelectorControls} autoFocus required
value={description} onChange={handleDescriptionChange}></Input>
{creatingContainer &&
<Spinner size='medium' label='Creating storage Container...' labelPosition='after' />
}
</DialogContent>
<DialogActions>
<DialogTrigger disableButtonEnhancement>
<Button appearance="secondary" disabled={creatingContainer}>Cancel</Button>
</DialogTrigger>
<Button appearance="primary"
value={name}
onClick={onContainerCreateClick}
disabled={creatingContainer || (name === '')}>Create storage Container</Button>
</DialogActions>
</DialogBody>
</DialogSurface>
</Dialog>
Tester la création de conteneurs
Nous allons maintenant tester l’application React côté client pour voir les effets de nos modifications pour créer des conteneurs dans l’application React.
À partir de la ligne de commande dans le dossier racine du projet, exécutez la commande suivante :
npm run start
Lorsque le navigateur se charge, connectez-vous à l’aide du même compte professionnel et scolaire que celui que vous avez utilisé.
Après la connexion, la page se recharge et doit maintenant inclure un bouton pour lancer la boîte de dialogue :
Sélectionnez le bouton Créer un conteneur de stockage pour ouvrir la boîte de dialogue. Notez que le bouton est désactivé jusqu’à ce que vous entrez un nom :
Entrez un nom et une description pour le conteneur, puis sélectionnez Créer un conteneur de stockage. Lors de la création du conteneur, les boutons sont désactivés et un Spinner
contrôle indique l’utilisateur qu’il fonctionne :
Une fois la boîte de dialogue supprimée, le sélecteur nouveau affiche notre nouveau conteneur !
Arrêtez le serveur en appuyant sur Ctrl + C dans la console.
Résumé
Dans cet exercice, vous avez mis à jour le projet existant pour créer et récupérer des conteneurs Incorporés SharePoint.