initial commit

This commit is contained in:
Zach 2021-09-27 22:44:13 -04:00
parent 39ea25afc2
commit 98f59421bf
43 changed files with 23324 additions and 0 deletions

View File

@ -0,0 +1,33 @@
# Logs
logs
*.log
npm-debug.log*
# Dependency directories
node_modules
# Build generated files
dist
lib
release
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

View File

@ -0,0 +1,12 @@
{
"@microsoft/generator-sharepoint": {
"version": "1.12.1",
"libraryName": "react-azure-group-view",
"libraryId": "bcbef560-eaf3-4560-8f6f-482eceaf14a5",
"environment": "spo",
"packageManager": "npm",
"isCreatingSolution": true,
"isDomainIsolated": false,
"componentType": "webpart"
}
}

View File

@ -0,0 +1,77 @@
# Graph Group Viewer
## Summary
This webpart will provide the functionality to search for groups in your tenant and allow you to view the details of the selected group as well as view a list of group members and export the list of members to a CSV file.
![picture of the web part in action](assets/preview.gif)
## Compatibility
![SPFx 1.12.1](https://img.shields.io/badge/SPFx-1.12.1-green.svg)
![Node.js LTS v14 | LTS v12 | LTS v10](https://img.shields.io/badge/Node.js-LTS%20v14%20%7C%20LTS%20v12%20%7C%20LTS%20v10-green.svg)
![SharePoint Online](https://img.shields.io/badge/SharePoint-Online-yellow.svg)
![Teams N/A: Untested with Microsoft Teams](https://img.shields.io/badge/Teams-N%2FA-lightgrey.svg "Untested with Microsoft Teams")
![Workbench Hosted: Does not work with local workbench](https://img.shields.io/badge/Workbench-Hosted-yellow.svg "Does not work with local workbench")
## Applies to
* [SharePoint Framework](https://docs.microsoft.com/sharepoint/dev/spfx/sharepoint-framework-overview)
* [Microsoft 365 tenant](https://docs.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment)
* [Microsoft Graph](https://docs.microsoft.com/en-us/graph/overview)
* [PnP React Controls](https://pnp.github.io/sp-dev-fx-controls-react/)
## Solution
Solution|Author(s)
--------|---------
react-graph-groupviewer | [Zach Roberts](https://github.com/zachroberts8668) ([@ZachSPODev](https://twitter.com/ZachSPODev))
## Version history
Version|Date|Comments
-------|----|--------
1.0|September 27, 2021|Initial release
## Prerequisites
There are no prerequisites to use this webpart.
## Minimal Path to Awesome
* Clone this repository
* If your SharePoint tenant does not already allow API access to the following Microsoft Graph permissions: Directory.Read.All, Group.Read.All and GroupMember.Read.All then please follow the below instructions.
* in the command line run:
* `npm install`
* `gulp build --ship`
* `gulp bundle --ship`
* `gulp package-solution --ship`
* browse to your SharePoint app catalog and load the SPFX package. Once loaded you will need to browse to your SharePoint Admin Center and under advanced you will need to open Api Access and allow the requests for Microsoft Graph.
* If you have the APIs permissions already allowed you can follow the below steps.
* in the command line run:
* `npm install`
* `gulp serve --nobrowser`
* browse to your hosted workbench and add the webpart.
## Features
This Web Part illustrates the following concepts on top of the SharePoint Framework:
* Using Microsoft Graph to search for groups and return group members for the selected group.
* Exporting loaded data to a CSV file using [CSVLink](https://github.com/react-csv/react-csv)
## 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.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=react-graph-groupviewer&authors=@zroberts8668&title=react-graph-groupviewer%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=react-graph-groupviewer&authors=@zroberts8668&title=react-graph-groupviewer%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=react-graph-groupviewer&authors=@zroberts8668&title=react-graph-groupviewer%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-graph-groupviewer" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@ -0,0 +1,20 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0",
"bundles": {
"azure-group-view-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/azureGroupView/AzureGroupViewWebPart.js",
"manifest": "./src/webparts/azureGroupView/AzureGroupViewWebPart.manifest.json"
}
]
}
},
"externals": {},
"localizedResources": {
"AzureGroupViewWebPartStrings": "lib/webparts/azureGroupView/loc/{locale}.js",
"PropertyControlStrings": "node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js",
"ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js"
}
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
"deployCdnPath": "./release/assets/"
}

View File

@ -0,0 +1,7 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
"workingDir": "./release/assets/",
"account": "<!-- STORAGE ACCOUNT NAME -->",
"container": "react-azure-group-view",
"accessKey": "<!-- ACCESS KEY -->"
}

View File

@ -0,0 +1,34 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"name": "react-graph-groupviewer-client-side-solution",
"id": "bcbef560-eaf3-4560-8f6f-482eceaf14a5",
"version": "1.0.0.0",
"includeClientSideAssets": true,
"isDomainIsolated": false,
"developer": {
"name": "",
"websiteUrl": "",
"privacyUrl": "",
"termsOfUseUrl": "",
"mpnId": ""
},
"webApiPermissionRequests": [
{
"resource": "Microsoft Graph",
"scope": "Directory.Read.All"
},
{
"resource": "Microsoft Graph",
"scope": "Group.Read.All"
},
{
"resource": "Microsoft Graph",
"scope": "GroupMember.Read.All"
}
]
},
"paths": {
"zippedPackage": "solution/react-graph-groupviewer.sppkg"
}
}

View File

@ -0,0 +1,10 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",
"port": 4321,
"https": true,
"initialPage": "https://localhost:5432/workbench",
"api": {
"port": 5432,
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
}
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
"cdnBasePath": "<!-- PATH TO CDN -->"
}

View File

@ -0,0 +1,16 @@
'use strict';
const build = require('@microsoft/sp-build-web');
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
var getTasks = build.rig.getTasks;
build.rig.getTasks = function () {
var result = getTasks.call(build.rig);
result.set('serve', result.get('serve-deprecated'));
return result;
};
build.initialize(require('gulp'));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
{
"name": "react-graph-groupviewer",
"version": "0.0.1",
"private": true,
"main": "lib/index.js",
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
"test": "gulp test"
},
"dependencies": {
"@microsoft/sp-core-library": "1.12.1",
"@microsoft/sp-lodash-subset": "1.12.1",
"@microsoft/sp-office-ui-fabric-core": "1.12.1",
"@microsoft/sp-property-pane": "1.12.1",
"@microsoft/sp-webpart-base": "1.12.1",
"@pnp/common": "^2.8.0",
"@pnp/graph": "^2.8.0",
"@pnp/logging": "^2.8.0",
"@pnp/odata": "^2.8.0",
"@pnp/spfx-controls-react": "^3.3.0",
"@pnp/spfx-property-controls": "3.2.0",
"office-ui-fabric-react": "7.156.0",
"react": "16.9.0",
"react-csv": "^2.0.3",
"react-dom": "16.9.0"
},
"devDependencies": {
"@types/react": "16.9.36",
"@types/react-dom": "16.9.8",
"@microsoft/sp-build-web": "1.12.1",
"@microsoft/sp-tslint-rules": "1.12.1",
"@microsoft/sp-module-interfaces": "1.12.1",
"@microsoft/sp-webpart-workbench": "1.12.1",
"@microsoft/rush-stack-compiler-3.7": "0.2.3",
"gulp": "~4.0.2",
"ajv": "~5.2.2",
"@types/webpack-env": "1.13.1"
}
}

View File

@ -0,0 +1 @@
// A file is required to be in the root of the /src directory by the TypeScript compiler

View File

@ -0,0 +1,27 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
"id": "bc258878-df14-4cf4-83d1-1032852bc307",
"alias": "AzureGroupViewWebPart",
"componentType": "WebPart",
// The "*" signifies that the version should be taken from the package.json
"version": "*",
"manifestVersion": 2,
// If true, the component can only be installed on sites where Custom Script is allowed.
// Components that allow authors to embed arbitrary script code should set this to true.
// https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
"requiresCustomScript": false,
"supportedHosts": ["SharePointWebPart"],
"preconfiguredEntries": [{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
"group": { "default": "Other" },
"title": { "default": "React Group View" },
"description": { "default": "Azure Group View description" },
"officeFabricIconFontName": "Page",
"properties": {
"description": "Azure Group View"
}
}]
}

View File

@ -0,0 +1,80 @@
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
IPropertyPaneConfiguration,
IPropertyPaneDropdownOption,
PropertyPaneDropdown,
PropertyPaneTextField
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import { graph } from "@pnp/graph";
import "@pnp/graph/groups";
import * as strings from 'AzureGroupViewWebPartStrings';
import { AzureGroupView, IAzureGroupViewProps } from './components';
export interface IAzureGroupViewWebPartProps {
description: string;
aadGroupId: string;
}
export default class AzureGroupViewWebPart extends BaseClientSideWebPart<IAzureGroupViewWebPartProps> {
private groupOptions: IPropertyPaneDropdownOption[] = [];
private groupOptionsLoading: boolean = false;
public render(): void {
const element: React.ReactElement<IAzureGroupViewProps> = React.createElement(
AzureGroupView,
{
description: this.properties.description,
aadGroupId: this.properties.aadGroupId
}
);
ReactDom.render(element, this.domElement);
}
protected onInit(): Promise<void> {
return super.onInit().then(_ => {
graph.setup({
spfxContext: this.context
});
});
}
protected onDispose(): void {
ReactDom.unmountComponentAtNode(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
})
]
}
]
}
]
};
}
}

View File

@ -0,0 +1,3 @@
.membersBtn {
padding-top: 10px;
}

View File

@ -0,0 +1,43 @@
import * as React from 'react';
import { IGroupDetailsProps } from './IGroupDetailsProps';
import { IGroupDetailsState } from './IGroupDetailsState';
import { PrimaryButton, Label, Text, Panel} from 'office-ui-fabric-react';
import styles from './GroupDetails.module.scss';
import { MembersList } from '../memberslist/MembersList';
export class GroupDetails extends React.Component<IGroupDetailsProps, IGroupDetailsState>{
constructor(props: IGroupDetailsProps) {
super(props);
this.state = {
showPanel: false
};
}
public render(): React.ReactElement<IGroupDetailsProps> {
return (
<div>
<hr />
<Text variant="large">Group Details - {this.props.selectedGroup.displayName}</Text>
<Label>Description:</Label>
<div>{this.props.selectedGroup.description}</div>
<div className={styles.membersBtn}>
<PrimaryButton iconProps={{iconName: 'People'}} text="View Members" onClick={this._handlePanel} />
</div>
{this.state.showPanel ?
<MembersList closePanel={this._handlePanel} showPanel={this.state.showPanel} groupName={this.props.selectedGroup.displayName} groupId={this.props.selectedGroup.id} />
: <div></div>
}
</div>
);
}
private _handlePanel = (): void => {
this.setState({
showPanel: !this.state.showPanel
});
}
}

View File

@ -0,0 +1,6 @@
import { IGroup } from "@pnp/graph/groups";
import { IAzureGroup } from "../../models";
export interface IGroupDetailsProps {
selectedGroup?: IAzureGroup;
}

View File

@ -0,0 +1,3 @@
export interface IGroupDetailsState {
showPanel?: boolean;
}

View File

@ -0,0 +1,60 @@
import * as React from 'react';
import { IGroupListProps } from './IGroupListProps';
import { IGroupListState } from './IGroupListState';
import { ListView, IViewField, SelectionMode } from "@pnp/spfx-controls-react/lib/ListView";
import { PrimaryButton } from 'office-ui-fabric-react';
import { IAzureGroup } from '../../models';
import { GroupDetails } from '../groupdetails/GroupDetails';
const view: IViewField[] = [
{
name: 'displayName',
displayName: 'Group Name',
minWidth: 150,
isResizable: true
}
];
export class GroupList extends React.Component<IGroupListProps, IGroupListState> {
constructor(props: IGroupListProps){
super(props);
this.state = {
selectedGroup: null
};
}
public render(): React.ReactElement<IGroupListProps> {
return (
<div>
<ListView
items={this.props.results}
viewFields={view}
selectionMode={SelectionMode.single}
selection={this._getSelection}
/>
{ this.state.selectedGroup === null ?
<div></div>
: <GroupDetails selectedGroup={this.state.selectedGroup} />
}
</div>
);
}
private _getSelection = (items: any[]) :void => {
console.log(items);
if(items.length !== 0){
const selected: IAzureGroup = {
displayName: items[0].displayName,
description: items[0].description,
id: items[0].id
};
this.setState({
selectedGroup: selected
});
}
}
}

View File

@ -0,0 +1,6 @@
import { IGroup } from "@pnp/graph/groups";
import { _Group } from "@pnp/graph/groups/types";
export interface IGroupListProps {
results?: IGroup[];
}

View File

@ -0,0 +1,5 @@
import { IAzureGroup } from "../../models";
export interface IGroupListState {
selectedGroup: IAzureGroup;
}

View File

@ -0,0 +1,2 @@
export * from './GroupList';
export * from './IGroupListProps';

View File

@ -0,0 +1 @@
export * from './main';

View File

@ -0,0 +1,74 @@
@import '~office-ui-fabric-react/dist/sass/References.scss';
.azureGroupView {
.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 {
@include ms-Grid-row;
@include ms-fontColor-white;
background-color: $ms-color-themeDark;
padding: 20px;
}
.column {
@include ms-Grid-col;
@include ms-lg10;
@include ms-xl8;
@include ms-xlPush2;
@include ms-lgPush1;
}
.title {
@include ms-font-xl;
@include ms-fontColor-white;
}
.subTitle {
@include ms-font-l;
@include ms-fontColor-white;
}
.description {
@include ms-font-l;
@include ms-fontColor-white;
}
.button {
// Our button
text-decoration: none;
height: 32px;
// Primary Button
min-width: 80px;
background-color: $ms-color-themePrimary;
border-color: $ms-color-themePrimary;
color: $ms-color-white;
// Basic Button
outline: transparent;
position: relative;
font-family: "Segoe UI WestEuropean","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif;
-webkit-font-smoothing: antialiased;
font-size: $ms-font-size-m;
font-weight: $ms-font-weight-regular;
border-width: 0;
text-align: center;
cursor: pointer;
display: inline-block;
padding: 0 16px;
.label {
font-weight: $ms-font-weight-semibold;
font-size: $ms-font-size-m;
height: 32px;
line-height: 32px;
margin: 0 4px;
vertical-align: top;
display: inline-block;
}
}
}

View File

@ -0,0 +1,42 @@
import * as React from 'react';
import styles from './AzureGroupView.module.scss';
import { IAzureGroupViewProps } from './IAzureGroupViewProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { PrimaryButton, TextField } from '@microsoft/office-ui-fabric-react-bundle';
import { graph } from "@pnp/graph";
import "@pnp/graph/groups";
import { IAzureGroupViewState } from './IAzureGroupViewState';
import { GroupList } from '../grouplist/GroupList';
import { GroupDetails } from '../groupdetails/GroupDetails';
export class AzureGroupView extends React.Component<IAzureGroupViewProps, IAzureGroupViewState> {
constructor(props: IAzureGroupViewProps) {
super(props);
this.state = {
searchResults: null,
};
}
public render(): React.ReactElement<IAzureGroupViewProps> {
return (
<div className={ styles.azureGroupView }>
<TextField label="Search Groups" onChange={(event: React.FormEvent<HTMLInputElement>, newValue: string) => {this._searchGroups(newValue);}} />
<br />
<GroupList results={this.state.searchResults} />
</div>
);
}
private _searchGroups = (searchText: string): void => {
graph.groups.search(`displayName:${searchText}`).top(5).get().then(groups => {
this.setState({
searchResults: groups
});
});
}
}

View File

@ -0,0 +1,4 @@
export interface IAzureGroupViewProps {
description: string;
aadGroupId?: string;
}

View File

@ -0,0 +1,5 @@
import { graph, Group, GroupType, Groups, IGroup, IGroupAddResult, IGroups } from "@pnp/graph/presets/all";
export interface IAzureGroupViewState {
searchResults?: any[];
}

View File

@ -0,0 +1,2 @@
export * from './AzureGroupView';
export * from './IAzureGroupViewProps';

View File

@ -0,0 +1,5 @@
export interface IMemberListState {
members?: any[];
membersCount: number;
isLoading: boolean;
}

View File

@ -0,0 +1,8 @@
import { PanelCallback } from "../../models";
export interface IMembersListProps {
groupName: string;
groupId: string;
showPanel: boolean;
closePanel: PanelCallback;
}

View File

@ -0,0 +1,4 @@
.exportBtn {
padding-top: 10px;
padding-bottom: 10px;
}

View File

@ -0,0 +1,95 @@
import * as React from 'react';
import { IMembersListProps } from './IMembersListProps';
import { IMemberListState } from './IMemberListState';
import { Panel, PanelType, Spinner, SpinnerSize, DefaultButton } from 'office-ui-fabric-react';
import { ListView, IViewField } from '@pnp/spfx-controls-react/lib/ListView';
import { graph } from '@pnp/graph/presets/all';
import { CSVLink } from 'react-csv';
import styles from './MembersList.module.scss';
const view: IViewField[] = [
{
name: 'displayName',
displayName: 'Name',
minWidth: 150,
isResizable: true
},
{
name: 'mail',
displayName: 'Email',
minWidth: 150,
isResizable: true
}
];
const csvHeaders = [
{ label: 'Name', key: 'displayName'},
{ label: 'Email', key: 'mail'}
];
export class MembersList extends React.Component<IMembersListProps, IMemberListState>{
constructor(props: IMembersListProps) {
super(props);
this.state = {
members: null,
membersCount: 0,
isLoading: false
};
}
public render(): React.ReactElement<IMembersListProps> {
return (
<div>
<Panel type={PanelType.medium} isOpen={this.props.showPanel} headerText={`${this.props.groupName} - Members (${this.state.membersCount})`} onDismiss={this._handlePanel}>
{this.state.isLoading ?
<div>
<Spinner label="Loading Members..." size={SpinnerSize.medium} />
</div>
:
<div>
<div className={styles.exportBtn}>
<CSVLink data={this.state.members} headers={csvHeaders} filename={`${this.props.groupName}-Members.csv`}>
<DefaultButton text="Export to CSV" />
</CSVLink>
</div>
<ListView
items={this.state.members}
viewFields={view}
showFilter={true}
filterPlaceHolder={"Search Members..."}
/>
</div>
}
</Panel>
</div>
);
}
public componentDidMount() {
this._loadMembers();
}
private _loadMembers = (): void => {
this.setState({isLoading: true});
this._getMembers(this.props.groupId).then(response => {
this.setState({
members: response,
membersCount: response.length,
isLoading: false
});
});
}
private async _getMembers(id: string) {
const members = await graph.groups.getById(id).members();
console.log(members);
return members;
}
private _handlePanel = (): void => {
this.props.closePanel();
}
}

View File

@ -0,0 +1,7 @@
define([], function() {
return {
"PropertyPaneDescription": "Description",
"BasicGroupName": "Group Name",
"DescriptionFieldLabel": "Description Field"
}
});

View File

@ -0,0 +1,10 @@
declare interface IAzureGroupViewWebPartStrings {
PropertyPaneDescription: string;
BasicGroupName: string;
DescriptionFieldLabel: string;
}
declare module 'AzureGroupViewWebPartStrings' {
const strings: IAzureGroupViewWebPartStrings;
export = strings;
}

View File

@ -0,0 +1,5 @@
export interface IAzureGroup {
displayName: string;
id: string;
description: string;
}

View File

@ -0,0 +1 @@
export type PanelCallback = () => void;

View File

@ -0,0 +1,2 @@
export * from './IAzureGroup';
export * from './PanelCallback';

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

View File

@ -0,0 +1,35 @@
{
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.7/includes/tsconfig-web.json",
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"jsx": "react",
"declaration": true,
"sourceMap": true,
"experimentalDecorators": true,
"skipLibCheck": true,
"outDir": "lib",
"inlineSources": false,
"strictNullChecks": false,
"noUnusedLocals": false,
"typeRoots": [
"./node_modules/@types",
"./node_modules/@microsoft"
],
"types": [
"webpack-env"
],
"lib": [
"es5",
"dom",
"es2015.collection",
"es2015.promise"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx"
]
}

View File

@ -0,0 +1,30 @@
{
"extends": "./node_modules/@microsoft/sp-tslint-rules/base-tslint.json",
"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-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-use-before-declare": true,
"no-with-statement": true,
"semicolon": true,
"trailing-comma": false,
"typedef": false,
"typedef-whitespace": false,
"use-named-parameter": true,
"variable-name": false,
"whitespace": false
}
}