Added the MSAL JS sample (#253)
This commit is contained in:
parent
b2b9c6ea76
commit
96936add47
|
@ -0,0 +1,25 @@
|
|||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
|
||||
[*]
|
||||
|
||||
# change these settings to your own preference
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# we recommend you to keep these unchanged
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[{package,bower}.json]
|
||||
indent_style = space
|
||||
indent_size = 4
|
|
@ -0,0 +1 @@
|
|||
* text=auto
|
|
@ -0,0 +1,32 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules
|
||||
|
||||
# Build generated files
|
||||
dist
|
||||
lib
|
||||
solution
|
||||
temp
|
||||
*.sppkg
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
||||
# Visual Studio files
|
||||
.ntvs_analysis.dat
|
||||
.vs
|
||||
bin
|
||||
obj
|
||||
|
||||
# Resx Generated Code
|
||||
*.resx.ts
|
||||
|
||||
# Styles Generated Code
|
||||
*.scss.ts
|
|
@ -0,0 +1,14 @@
|
|||
# Folders
|
||||
.vscode
|
||||
coverage
|
||||
node_modules
|
||||
sharepoint
|
||||
src
|
||||
temp
|
||||
|
||||
# Files
|
||||
*.csproj
|
||||
.git*
|
||||
.yo-rc.json
|
||||
gulpfile.js
|
||||
tsconfig.json
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"version": "1.1.1",
|
||||
"libraryName": "react-msal-msgraph",
|
||||
"libraryId": "169d1e68-4272-4d99-ac26-e4acd43d62fd",
|
||||
"environment": "spo"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
# Microsoft Authentication Library (MSAL JS) authentication sample
|
||||
|
||||
## Summary
|
||||
|
||||
Sample SharePoint Framework web part which makes use of the [Microsoft Authentication Library (MSAL JS)](https://github.com/AzureAD/microsoft-authentication-library-for-js) to call the Microsoft Graph.
|
||||
|
||||
### MSAL WP
|
||||
|
||||
The sample web part will retrieve an access token with the `User.Read` and `Mail.Read` scope. Once an access token is retrieved, it will do a call to receive the current user and its mail messages.
|
||||
|
||||
![Permission scopes](./assets/permission-scopes.png)
|
||||
|
||||
After you gave permissions, the following will information will get displayed:
|
||||
|
||||
![The MSAL web part displayed in SharePoint workbench](./assets/msal-wp-output.png)
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
![drop](https://img.shields.io/badge/drop-GA-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework](http://dev.office.com/sharepoint/docs/spfx/sharepoint-framework-overview)
|
||||
* [Office 365 developer tenant](http://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant)
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
react-msal-msgraph|Elio Struyf (MVP, [U2U](https://www.u2u.be), [@eliostruyf](https://www.twitter.com/eliostruyf))
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0.0|March 17, 2017|Initial release
|
||||
|
||||
## Disclaimer
|
||||
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Office 365 subscription with SharePoint Online and Exchange
|
||||
|
||||
## Minimal Path to Awesome
|
||||
|
||||
- Clone this repo
|
||||
- Go and register a new application on [https://apps.dev.microsoft.com](https://apps.dev.microsoft.com)
|
||||
- Once logged in, click on **add an app**
|
||||
- Specify the application name, and click create
|
||||
- Click on **add platform**, and choose **web**
|
||||
- Specify the workbench URL and be sure that **allow implicit flow** is enabled
|
||||
- Click on save to store these changes
|
||||
|
||||
![Web URL configuration and implicit flow](./assets/redirect-url.png)
|
||||
|
||||
- Copy the **application id** and change add this to the [MsalWP.tsx file on line 20](./src/webparts/msalWp/components/MsalWp.tsx#20)
|
||||
- Run `npm i`
|
||||
- Run `gulp serve --nobrowser`
|
||||
- Test out your web part in the local or hosted workbench
|
||||
|
||||
## Features
|
||||
|
||||
Sample web part in this solution illustrates the following concepts on top of the SharePoint Framework:
|
||||
|
||||
- using React for building SharePoint Framework client-side web parts
|
||||
- using Office UI Fabric React styles for building user experience consistent with SharePoint and Office
|
||||
- on-demand authentication with the Azure Active Directory using the MSAL JS library
|
||||
- communicating with the Microsoft Graph using its REST API
|
||||
- using the MSAL JS library with SharePoint Framework web parts built using React
|
||||
|
||||
![](https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-msal-msgraph)
|
Binary file not shown.
After Width: | Height: | Size: 85 KiB |
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"entries": [{
|
||||
"entry": "./lib/webparts/msalWp/MsalWpWebPart.js",
|
||||
"manifest": "./src/webparts/msalWp/MsalWpWebPart.manifest.json",
|
||||
"outputPath": "./dist/msal-wp.bundle.js"
|
||||
}],
|
||||
"externals": {
|
||||
"Msal": {
|
||||
"path": "https://secure.aadcdn.microsoftonline-p.com/lib/0.1.1/js/msal.min.js",
|
||||
"globalName": "Msal"
|
||||
}
|
||||
},
|
||||
"localizedResources": {
|
||||
"msalWpStrings": "webparts/msalWp/loc/{locale}.js"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"workingDir": "./temp/deploy/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "react-msal-msgraph",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"solution": {
|
||||
"name": "react-msal-msgraph-client-side-solution",
|
||||
"id": "169d1e68-4272-4d99-ac26-e4acd43d62fd",
|
||||
"version": "1.0.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/react-msal-msgraph.sppkg"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"port": 4321,
|
||||
"initialPage": "https://localhost:5432/workbench",
|
||||
"https": true,
|
||||
"api": {
|
||||
"port": 5432,
|
||||
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
// Display errors as warnings
|
||||
"displayAsWarning": true,
|
||||
// The TSLint task may have been configured with several custom lint rules
|
||||
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
|
||||
// project). If true, this flag will deactivate any of these rules.
|
||||
"removeExistingRules": true,
|
||||
// When true, the TSLint task is configured with some default TSLint "rules.":
|
||||
"useDefaultConfigAsBase": false,
|
||||
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
|
||||
// which are active, other than the list of rules below.
|
||||
"lintConfig": {
|
||||
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
|
||||
"rules": {
|
||||
"class-name": false,
|
||||
"export-name": false,
|
||||
"forin": false,
|
||||
"label-position": false,
|
||||
"member-access": true,
|
||||
"no-arg": false,
|
||||
"no-console": false,
|
||||
"no-construct": false,
|
||||
"no-duplicate-case": true,
|
||||
"no-duplicate-variable": true,
|
||||
"no-eval": false,
|
||||
"no-function-expression": true,
|
||||
"no-internal-module": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-unnecessary-semicolons": true,
|
||||
"no-unused-expression": true,
|
||||
"no-unused-imports": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-with-statement": true,
|
||||
"semicolon": true,
|
||||
"trailing-comma": false,
|
||||
"typedef": false,
|
||||
"typedef-whitespace": false,
|
||||
"use-named-parameter": true,
|
||||
"valid-typeof": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const gulp = require('gulp');
|
||||
const build = require('@microsoft/sp-build-web');
|
||||
|
||||
build.initialize(gulp);
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "react-msal-msgraph",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "~1.1.0",
|
||||
"@microsoft/sp-webpart-base": "~1.1.1",
|
||||
"@types/react": "0.14.46",
|
||||
"@types/react-addons-shallow-compare": "0.14.17",
|
||||
"@types/react-addons-test-utils": "0.14.15",
|
||||
"@types/react-addons-update": "0.14.14",
|
||||
"@types/react-dom": "0.14.18",
|
||||
"@types/webpack-env": ">=1.12.1 <1.14.0",
|
||||
"msal": "0.1.1",
|
||||
"react": "15.4.2",
|
||||
"react-dom": "15.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "~1.1.0",
|
||||
"@microsoft/sp-module-interfaces": "~1.1.0",
|
||||
"@microsoft/sp-webpart-workbench": "~1.1.0",
|
||||
"@types/chai": ">=3.4.34 <3.6.0",
|
||||
"@types/mocha": ">=2.2.33 <2.6.0",
|
||||
"gulp": "~3.9.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp clean",
|
||||
"test": "gulp test"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export interface IMsalWpWebPartProps {
|
||||
description: string;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
|
||||
|
||||
"id": "5ff21af8-04ea-478a-a640-919b29ba5ff4",
|
||||
"alias": "MsalWpWebPart",
|
||||
"componentType": "WebPart",
|
||||
"version": "*", // The "*" signifies that the version should be taken from the package.json
|
||||
"manifestVersion": 2,
|
||||
|
||||
/**
|
||||
* This property should only be set to true if it is certain that the webpart does not
|
||||
* allow arbitrary scripts to be called
|
||||
*/
|
||||
"safeWithCustomScriptDisabled": false,
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "5ff21af8-04ea-478a-a640-919b29ba5ff4",
|
||||
"group": { "default": "Under Development" },
|
||||
"title": { "default": "MSAL WP" },
|
||||
"description": { "default": "MSAL WP description" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"properties": {
|
||||
"description": "MSAL WP"
|
||||
}
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import { Version } from '@microsoft/sp-core-library';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
|
||||
import * as strings from 'msalWpStrings';
|
||||
import MsalWp from './components/MsalWp';
|
||||
import { IMsalWpProps } from './components/IMsalWpProps';
|
||||
import { IMsalWpWebPartProps } from './IMsalWpWebPartProps';
|
||||
|
||||
export default class MsalWpWebPart extends BaseClientSideWebPart<IMsalWpWebPartProps> {
|
||||
|
||||
public render(): void {
|
||||
const element: React.ReactElement<IMsalWpProps > = React.createElement(
|
||||
MsalWp,
|
||||
{
|
||||
description: this.properties.description,
|
||||
context: this.context
|
||||
}
|
||||
);
|
||||
|
||||
ReactDom.render(element, this.domElement);
|
||||
}
|
||||
|
||||
protected get dataVersion(): Version {
|
||||
return Version.parse('1.0');
|
||||
}
|
||||
|
||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
header: {
|
||||
description: strings.PropertyPaneDescription
|
||||
},
|
||||
groups: [
|
||||
{
|
||||
groupName: strings.BasicGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneTextField('description', {
|
||||
label: strings.DescriptionFieldLabel
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
import { IWebPartContext } from "@microsoft/sp-webpart-base";
|
||||
|
||||
export interface IMsalWpProps {
|
||||
description: string;
|
||||
context: IWebPartContext;
|
||||
}
|
||||
|
||||
export interface IMsalWpState {
|
||||
loading?: boolean;
|
||||
loggedIn?: boolean;
|
||||
person?: IPerson;
|
||||
mails?: IMail[];
|
||||
}
|
||||
|
||||
export interface IPerson {
|
||||
id: string;
|
||||
businessPhones?: any[];
|
||||
displayName?: string;
|
||||
givenName?: string;
|
||||
jobTitle?: string;
|
||||
mail?: string;
|
||||
mobilePhone?: any;
|
||||
officeLocation?: any;
|
||||
preferredLanguage?: string;
|
||||
surname?: string;
|
||||
userPrincipalName?: string;
|
||||
}
|
||||
|
||||
export interface IMails {
|
||||
value: IMail[];
|
||||
}
|
||||
|
||||
export interface IMail {
|
||||
subject: string;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
.msalWp {
|
||||
.container {
|
||||
max-width: 700px;
|
||||
margin: 0px auto;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
/// <reference path="../../../../node_modules/msal/out/msal.d.ts" />
|
||||
|
||||
import * as React from 'react';
|
||||
import styles from './MsalWp.module.scss';
|
||||
import { IMsalWpProps, IMsalWpState, IPerson, IMails, IMail } from './IMsalWpProps';
|
||||
import { HttpClient } from "@microsoft/sp-http";
|
||||
import { PrimaryButton, Persona, PersonaSize, PersonaInitialsColor, List, Spinner, SpinnerType } from 'office-ui-fabric-react';
|
||||
|
||||
/**
|
||||
* Load the MSAL library
|
||||
*/
|
||||
require('Msal');
|
||||
declare const Msal;
|
||||
|
||||
/**
|
||||
* MSAL Config
|
||||
* Register your app here: https://apps.dev.microsoft.com/
|
||||
*/
|
||||
const msalconfig = {
|
||||
clientID: "00000000-0000-0000-0000-000000000000", // Azure AD Application
|
||||
redirectUri: location.origin
|
||||
};
|
||||
|
||||
const scopes = ["User.Read", "Mail.Read"];
|
||||
|
||||
export default class MsalWp extends React.Component<IMsalWpProps, IMsalWpState> {
|
||||
private clientApplication: Msal.UserAgentApplication;
|
||||
|
||||
constructor(props: IMsalWpProps) {
|
||||
super(props);
|
||||
|
||||
// Set the initial state of the component
|
||||
this.state = {
|
||||
loading: false,
|
||||
loggedIn: false,
|
||||
person: null,
|
||||
mails: []
|
||||
};
|
||||
|
||||
// Initialize the user agent application for MSAL
|
||||
if (!this.clientApplication) {
|
||||
this.clientApplication = new Msal.UserAgentApplication(msalconfig.clientID, null, (errorDesc, token, error, tokenType) => {
|
||||
// Called after loginRedirect or acquireTokenPopup
|
||||
});
|
||||
}
|
||||
|
||||
// Check if the user can be retrieved and automatically get your data
|
||||
if (this.clientApplication.getUser()) {
|
||||
this._getAccessToken();
|
||||
}
|
||||
|
||||
this._login = this._login.bind(this);
|
||||
this._getAccessToken = this._getAccessToken.bind(this);
|
||||
this._getCrntUser = this._getCrntUser.bind(this);
|
||||
this._getMessages = this._getMessages.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that will login the user and call the Microsoft Graph
|
||||
*/
|
||||
private _login(): void {
|
||||
// Login the user
|
||||
if (this.clientApplication.getUser()) {
|
||||
this._getAccessToken();
|
||||
} else {
|
||||
this.clientApplication.loginPopup(scopes).then((idToken: string) => {
|
||||
this._getAccessToken();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an accessToken for the Microsoft Graph
|
||||
*/
|
||||
private _getAccessToken(): void {
|
||||
this.state = {
|
||||
loading: true
|
||||
};
|
||||
// Retrieve a accessToken to call the Microsoft Graph
|
||||
this.clientApplication.acquireTokenSilent(scopes).then((token: string) => {
|
||||
this._getCrntUser(token);
|
||||
this._getMessages(token);
|
||||
}, (error) => {
|
||||
// Interaction required
|
||||
if (error) {
|
||||
this.clientApplication.acquireTokenPopup(scopes).then((token: string) => {
|
||||
this._getCrntUser(token);
|
||||
this._getMessages(token);
|
||||
}, (err: string) => {
|
||||
// Something went wrong
|
||||
console.log('Error:', err);
|
||||
this.setState({
|
||||
loading: false
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the current user via the Microsoft Graph
|
||||
*/
|
||||
private _getCrntUser(token: string): void {
|
||||
// Call the Microsoft Graph
|
||||
this.props.context.httpClient.get('https://graph.microsoft.com/v1.0/me', HttpClient.configurations.v1, {
|
||||
headers: {
|
||||
"authorization": `Bearer ${token}`
|
||||
}
|
||||
}).then(response => {
|
||||
return response.json();
|
||||
}).then((data: IPerson) => {
|
||||
this.setState({
|
||||
loggedIn: true,
|
||||
person: data,
|
||||
loading: false
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mails of the current user
|
||||
*/
|
||||
private _getMessages(token: string): void {
|
||||
// Call the Microsoft Graph
|
||||
this.props.context.httpClient.get('https://graph.microsoft.com/v1.0/me/messages', HttpClient.configurations.v1, {
|
||||
headers: {
|
||||
"authorization": `Bearer ${token}`
|
||||
}
|
||||
}).then(response => {
|
||||
return response.json();
|
||||
}).then((data: IMails) => {
|
||||
this.setState({
|
||||
mails: data.value,
|
||||
loading: false
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Component render
|
||||
*/
|
||||
public render(): React.ReactElement<IMsalWpProps> {
|
||||
if (this.state.loading) {
|
||||
return <Spinner type={ SpinnerType.large } label="Retrieving your data" />;
|
||||
}
|
||||
|
||||
const loginBtn: JSX.Element = this.state.loggedIn ? <div /> : <PrimaryButton text='Login' onClick={this._login} />;
|
||||
|
||||
let userInfo: JSX.Element = <div />;
|
||||
if (this.state.loggedIn && this.state.person) {
|
||||
userInfo = <Persona
|
||||
primaryText={this.state.person.displayName}
|
||||
imageInitials={`${this.state.person.givenName.slice(0, 1)}${this.state.person.surname.slice(0, 1)}`}
|
||||
secondaryText={this.state.person.jobTitle}
|
||||
optionalText="w00t"
|
||||
tertiaryText={this.state.person.mail}
|
||||
size={PersonaSize.extraLarge}
|
||||
hidePersonaDetails={false}
|
||||
initialsColor={PersonaInitialsColor.red}
|
||||
/>;
|
||||
}
|
||||
|
||||
let mails: JSX.Element = <div />;
|
||||
if (this.state.mails.length > 0) {
|
||||
mails = <p className="ms-font-l ms-fontColor-neutralPrimary">Your mails</p>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.msalWp}>
|
||||
<div className={styles.container}>
|
||||
<div className={`ms-Grid-row ms-bgColor-neutralLight ms-fontColor-neutralPrimary ${styles.row}`}>
|
||||
<div className="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1">
|
||||
<p className="ms-font-xl ms-fontColor-neutralPrimary">SPFx WP sample with the MSAL library</p>
|
||||
|
||||
{loginBtn}
|
||||
|
||||
{userInfo}
|
||||
|
||||
{mails}
|
||||
|
||||
<List items={this.state.mails} onRenderCell={(item: IMail, index: number) => (
|
||||
<div>{index++}: {item.subject}</div>
|
||||
)} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
declare interface IMsalWpStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
DescriptionFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'msalWpStrings' {
|
||||
const strings: IMsalWpStrings;
|
||||
export = strings;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/// <reference types="mocha" />
|
||||
|
||||
import { assert } from 'chai';
|
||||
|
||||
describe('MsalWpWebPart', () => {
|
||||
it('should do something', () => {
|
||||
assert.ok(true);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "commonjs",
|
||||
"jsx": "react",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"types": [
|
||||
"es6-promise",
|
||||
"es6-collections",
|
||||
"webpack-env"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Type definitions for Microsoft ODSP projects
|
||||
// Project: ODSP
|
||||
|
||||
/* Global definition for UNIT_TEST builds
|
||||
Code that is wrapped inside an if(UNIT_TEST) {...}
|
||||
block will not be included in the final bundle when the
|
||||
--ship flag is specified */
|
||||
declare const UNIT_TEST: boolean;
|
||||
|
||||
/* Global defintion for SPO builds */
|
||||
declare const DATACENTER: boolean;
|
|
@ -0,0 +1 @@
|
|||
/// <reference path="@ms/odsp.d.ts" />
|
Loading…
Reference in New Issue