Merge pull request #1568 from russgove/dev

This commit is contained in:
Hugo Bernier 2020-10-31 00:49:07 -04:00 committed by GitHub
commit a833b06a71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 22072 additions and 25471 deletions

View File

@ -21,9 +21,9 @@ React-securitygrid is an SPFX webpart that uses React and Office-UI-Fabric to re
![config panel](./src/images/MainDisplay.gif) ![config panel](./src/images/MainDisplay.gif)
Empty libraries are displayed withh a black folder icon, those with items are displayed with a white folder. The user can expand a list or library by clicking on the desired row. (If the library or folder has more than 5000 items an error will be displayed ) For deeply nested folders the Title column can be resized by drag and drop. The display shows a the appropriate icpn circle if the user has the selected permission to the given list, library, file or folder. (NOTE:The grid does not currently take into account access give via membership in an active directory group-- coming soon!). IMPORTANT: The user must have permissions to access lists and enumerate permissions in order to view the grid. Empty libraries are displayed with a black folder icon, those with items are displayed with a white folder. The user can expand a list or library by clicking on the desired row. (If the library or folder has more than 5000 items an error will be displayed ) For deeply nested folders the Title column can be resized by drag and drop. The display shows a the appropriate icon circle if the user has the selected permission to the given list, library, file or folder. (NOTE:The grid does not currently take into account access give via membership in an active directory group-- coming soon!). IMPORTANT: The user must have permissions to access lists and enumerate permissions in order to view the grid.
The user can change the permission being tested by cliking the Permission in the command bar and selecting a new Permission: The user can change the permission being tested by clicking the Permission in the command bar and selecting a new Permission:
![permission panel](./src/images/selectPermissionsPopout.PNG) ![permission panel](./src/images/selectPermissionsPopout.PNG)
@ -52,7 +52,7 @@ User Settings
The Show Email or Name Toggle determines whether the name or email is displayed by default. The Show Email or Name Toggle determines whether the name or email is displayed by default.
The Show Security Groups checkbox determines whether SharePoint Security groups are included in the grid. The Show Security Groups checkbox determines whether SharePoint Security groups are included in the grid.
The Show Users checkbox determines whether Users are included in the grid. The Show Users checkbox determines whether Users are included in the grid.
The Only show users with permissions toggle determines whether the grid shold diplay all users with access to the web, or only users with the selected permission The Only show users with permissions toggle determines whether the grid should display all users with access to the web, or only users with the selected permission
![config panel](./src/images/Permissions.gif) ![config panel](./src/images/Permissions.gif)
The Let Users Select users checkbox determines whether Users can filter the selected users in the grid. The Let Users Select users checkbox determines whether Users can filter the selected users in the grid.
@ -60,8 +60,8 @@ Display Settings
The Initial Title column width determines the initial width of the Title column(it can be resized). The Initial Title column width determines the initial width of the Title column(it can be resized).
The second configuarion pannel allows the owner to configure the List Settings The second configuration panel allows the owner to configure the List Settings
![List Confoguration panel](./src/images/ListConfiguration.PNG) ![List Configuration panel](./src/images/ListConfiguration.PNG)
List Settings List Settings
@ -82,7 +82,7 @@ This is a port of an Angular 1.3 SharePoint hosted App at https://github.com/rus
## Used SharePoint Framework Version ## Used SharePoint Framework Version
![version](https://img.shields.io/badge/version-1.10-green.svg) ![SPFx 1.10.0](https://img.shields.io/badge/version-1.10-green.svg)
## Applies to ## Applies to
@ -103,6 +103,7 @@ Solution|Author(s)
Version|Date|Comments Version|Date|Comments
-------|----|-------- -------|----|--------
1.0.0.3|October 28, 2020 | Update to office-ui-fabric-react 7.148.1, fixing icons and indentation for sub-folders
1.0.0.2|April 5, 2021| Updates to SPFx 1.10; Allow display of multiple permissions 1.0.0.2|April 5, 2021| Updates to SPFx 1.10; Allow display of multiple permissions
1.0.0.1|April 25, 2018|Update to SPFx 1.4.1 1.0.0.1|April 25, 2018|Update to SPFx 1.4.1
1.0.0.0|December 31, 2016|Initial version 1.0.0.0|December 31, 2016|Initial version

View File

@ -1,13 +1,13 @@
{ {
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json", "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": { "solution": {
"includeClientSideAssets": true, "includeClientSideAssets": true,
"isDomainIsolated": false, "isDomainIsolated": false,
"name": "spsecurity-webpart-3-client-side-solution", "name": "spsecurity-webpart-3-client-side-solution",
"id": "788271fb-ee9b-40df-8381-eb3dc70d1982", "id": "788271fb-ee9b-40df-8381-eb3dc70d1982",
"version": "1.0.0.1" "version": "1.0.0.3"
}, },
"paths": { "paths": {
"zippedPackage": "solution/spsecurity-webpart-3.sppkg" "zippedPackage": "solution/spsecurity-webpart-3.sppkg"
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +1,54 @@
{ {
"main": "lib/index.js", "main": "lib/index.js",
"name": "spsecurity-webpart-3", "name": "spsecurity-webpart-3",
"version": "0.0.1", "version": "0.0.1",
"private": true, "private": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
}, },
"resolutions": { "resolutions": {
"@types/react": "16.8.8" "@types/react": "16.8.8"
}, },
"dependencies": { "dependencies": {
"@pnp/common": "1.3.3", "@pnp/common": "1.3.3",
"@pnp/logging": "1.3.3", "@pnp/logging": "1.3.3",
"@pnp/odata": "1.3.3", "@pnp/odata": "1.3.3",
"@pnp/sp": "1.3.3", "@pnp/sp": "1.3.3",
"@pnp/spfx-property-controls": "1.0.0", "@pnp/spfx-property-controls": "1.0.0",
"@types/es6-promise": "0.0.33", "@types/es6-promise": "0.0.33",
"@types/react": "16.8.8", "@types/react": "16.8.8",
"@types/react-dom": "16.8.3", "@types/react-dom": "16.8.3",
"@types/webpack-env": "1.13.1", "@types/webpack-env": "1.13.1",
"lodash": "^4.17.4", "@uifabric/file-type-icons": "7.6.16",
"natives": "^1.1.6", "lodash": "^4.17.4",
"office-ui-fabric-react": "6.189.2", "natives": "^1.1.6",
"react": "16.8.5", "office-ui-fabric-react": "7.148.1",
"react-dom": "16.8.5" "react": "16.8.5",
}, "react-dom": "16.8.5"
"devDependencies": { },
"@microsoft/rush-stack-compiler-3.2": "0.6.8", "devDependencies": {
"@microsoft/rush-stack-compiler-3.3": "0.3.5", "@microsoft/rush-stack-compiler-3.2": "0.6.8",
"@microsoft/sp-build-web": "1.10.0", "@microsoft/rush-stack-compiler-3.3": "0.3.5",
"@microsoft/sp-core-library": "1.10.0", "@microsoft/sp-build-web": "1.10.0",
"@microsoft/sp-lodash-subset": "1.10.0", "@microsoft/sp-core-library": "1.10.0",
"@microsoft/sp-module-interfaces": "1.10.0", "@microsoft/sp-lodash-subset": "1.10.0",
"@microsoft/sp-office-ui-fabric-core": "1.10.0", "@microsoft/sp-module-interfaces": "1.10.0",
"@microsoft/sp-property-pane": "1.10.0", "@microsoft/sp-office-ui-fabric-core": "1.10.0",
"@microsoft/sp-tslint-rules": "1.10.0", "@microsoft/sp-property-pane": "1.10.0",
"@microsoft/sp-webpart-base": "1.10.0", "@microsoft/sp-tslint-rules": "1.10.0",
"@microsoft/sp-webpart-workbench": "1.10.0", "@microsoft/sp-webpart-base": "1.10.0",
"@types/chai": "3.4.34", "@microsoft/sp-webpart-workbench": "1.10.0",
"@types/mocha": "2.2.38", "@types/chai": "3.4.34",
"ajv": "~5.2.2", "@types/mocha": "2.2.38",
"gulp": "~3.9.1", "ajv": "~5.2.2",
"i": "0.3.6", "gulp": "~3.9.1",
"npm": "6.14.6", "i": "0.3.6",
"tslint-microsoft-contrib": "5.0.0" "npm": "6.14.6",
}, "tslint-microsoft-contrib": "5.0.0"
"scripts": { },
"build": "gulp bundle", "scripts": {
"clean": "gulp clean", "build": "gulp bundle",
"test": "gulp test" "clean": "gulp clean",
} "test": "gulp test"
}
} }

View File

@ -1,21 +1,16 @@
import * as React from "react";
import * as ReactDom from "react-dom";
import { Version } from "@microsoft/sp-core-library"; import { Version } from "@microsoft/sp-core-library";
import { SPPermission } from "@microsoft/sp-page-context"; import { SPPermission } from "@microsoft/sp-page-context";
import { PropertyFieldListPicker, PropertyFieldListPickerOrderBy } from '@pnp/spfx-property-controls/lib/PropertyFieldListPicker'; import { IPropertyPaneConfiguration, IPropertyPaneDropdownOption, PropertyPaneCheckbox, PropertyPaneDropdown, PropertyPaneSlider, PropertyPaneTextField, PropertyPaneToggle } from "@microsoft/sp-property-pane";
import { PropertyFieldSelectedPermissions, IPropertyFieldSelectedPermissionsProps } from "./containers/PropertyFieldSelectedPermissions";
import { sp } from "@pnp/sp";
import * as strings from "spSecurityStrings";
import SpSecurity from "./components/SpSecurity";
import { ISpSecurityProps } from "./components/ISpSecurityProps";
import { ISpSecurityWebPartProps } from "./ISpSecurityWebPartProps";
import { BaseClientSideWebPart } from "@microsoft/sp-webpart-base"; import { BaseClientSideWebPart } from "@microsoft/sp-webpart-base";
import { import { sp } from "@pnp/sp";
IPropertyPaneConfiguration, PropertyPaneCheckbox, import { PropertyFieldListPicker, PropertyFieldListPickerOrderBy } from '@pnp/spfx-property-controls/lib/PropertyFieldListPicker';
IPropertyPaneDropdownOption, PropertyPaneDropdown, PropertyPaneTextField, import * as React from "react";
PropertyPaneToggle, PropertyPaneSlider import * as ReactDom from "react-dom";
} from "@microsoft/sp-property-pane";
import { ISpSecurityProps } from "./components/ISpSecurityProps";
import SpSecurity from "./components/SpSecurity";
import { PropertyFieldSelectedPermissions } from "./containers/PropertyFieldSelectedPermissions";
import { ISpSecurityWebPartProps } from "./ISpSecurityWebPartProps";
export default class SpSecurityWebPart extends BaseClientSideWebPart<ISpSecurityWebPartProps> { export default class SpSecurityWebPart extends BaseClientSideWebPart<ISpSecurityWebPartProps> {
public onInit(): Promise<void> { public onInit(): Promise<void> {

View File

@ -1,34 +1,31 @@
import * as React from "react"; import { Environment, EnvironmentType } from '@microsoft/sp-core-library';
import styles from "./SpSecurity.module.scss";
import { ISpSecurityProps } from "./ISpSecurityProps";
import { ISpSecurityState } from "./ISpSecurityState";
import { ILegendProps, Legend } from "./Legend";
import SPSecurityService from "../../SPSecurityService";
import { SPListItem, SPList, SPSiteUser, Helpers } from "../../SPSecurityService";
import { SPPermission } from "@microsoft/sp-page-context"; import { SPPermission } from "@microsoft/sp-page-context";
import { indexOf, findIndex, find, filter, } from "lodash"; import { getFileTypeIconProps, initializeFileTypeIcons } from '@uifabric/file-type-icons';
import { DetailsList, IColumn, SelectionMode, IDetailsRowProps, Selection } from 'office-ui-fabric-react/lib/DetailsList'; import { filter, find, findIndex } from "lodash";
import { Icon } from 'office-ui-fabric-react/lib/Icon';
import { Checkbox } from 'office-ui-fabric-react/lib/Checkbox'; import { Checkbox } from 'office-ui-fabric-react/lib/Checkbox';
import { CommandBar } from "office-ui-fabric-react/lib/CommandBar"; import { CommandBar } from "office-ui-fabric-react/lib/CommandBar";
import { Stack } from "office-ui-fabric-react/lib/Stack"; import { ContextualMenuItemType, IContextualMenuItem } from "office-ui-fabric-react/lib/ContextualMenu";
import { Spinner } from "office-ui-fabric-react/lib/Spinner"; import { DetailsList, IColumn, Selection, SelectionMode } from 'office-ui-fabric-react/lib/DetailsList';
import { IContextualMenuItem, ContextualMenuItemType } from "office-ui-fabric-react/lib/ContextualMenu"; import { Icon } from 'office-ui-fabric-react/lib/Icon';
import { ISelectedPermission } from "../ISpSecurityWebPartProps";
import { Panel, PanelType } from "office-ui-fabric-react/lib/Panel"; import { Panel, PanelType } from "office-ui-fabric-react/lib/Panel";
import { Spinner } from "office-ui-fabric-react/lib/Spinner";
import * as React from "react";
import SPSecurityService from "../../SPSecurityService";
import { Helpers, SPList, SPListItem, SPSiteUser } from "../../SPSecurityService";
import SelectedPermissionsPanel from "../containers/SelectedPermissionsPanel"; import SelectedPermissionsPanel from "../containers/SelectedPermissionsPanel";
import { css } from "@uifabric/utilities/lib/css"; import { ISelectedPermission } from "../ISpSecurityWebPartProps";
import { import { ISpSecurityProps } from "./ISpSecurityProps";
Environment, import { ISpSecurityState } from "./ISpSecurityState";
EnvironmentType import { Legend } from "./Legend";
} from '@microsoft/sp-core-library'; import styles from "./SpSecurity.module.scss";
/* tslint:disable */ /* tslint:disable */
export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSecurityState> { export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSecurityState> {
private svc: SPSecurityService = new SPSecurityService("ss"); private svc: SPSecurityService = new SPSecurityService("ss");
private userSelection = new Selection(); private userSelection = new Selection();
private listSelection = new Selection(); private listSelection = new Selection();
private validBrandIcons = " accdb csv docx dotx mpp mpt odp ods odt one onepkg onetoc potx ppsx pptx pub vsdx vssx vstx xls xlsx xltx xsn "; constructor(props: any) {
constructor(props: any) {
super(props); super(props);
this.state = { this.state = {
securityInfo: { siteUsers: [], siteGroups: [], roleDefinitions: [], lists: [] }, securityInfo: { siteUsers: [], siteGroups: [], roleDefinitions: [], lists: [] },
@ -39,7 +36,7 @@ export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSec
showEmail: this.props.showEmail, showEmail: this.props.showEmail,
securityInfoLoaded: false, securityInfoLoaded: false,
showPermissionsPanel: false, showPermissionsPanel: false,
errors:[] errors: []
}; };
@ -54,8 +51,13 @@ export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSec
this.parentIsExpanded = this.parentIsExpanded.bind(this); this.parentIsExpanded = this.parentIsExpanded.bind(this);
this.renderUserSelected = this.renderUserSelected.bind(this); this.renderUserSelected = this.renderUserSelected.bind(this);
} }
public componentDidMount(): void {
debugger;
initializeFileTypeIcons();
}
public componentDidUpdate(): void { public componentDidUpdate(): void {
// disable postback of buttons. see https://github.com/SharePoint/sp-dev-docs/issues/492 // disable postback of buttons. see https://github.com/SharePoint/sp-dev-docs/issues/492
if (Environment.type === EnvironmentType.ClassicSharePoint) { if (Environment.type === EnvironmentType.ClassicSharePoint) {
const buttons: NodeListOf<HTMLButtonElement> = this.props.domElement.getElementsByTagName('button'); const buttons: NodeListOf<HTMLButtonElement> = this.props.domElement.getElementsByTagName('button');
for (let i: number = 0; i < buttons.length; i++) { for (let i: number = 0; i < buttons.length; i++) {
@ -81,44 +83,44 @@ export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSec
public componentWillMount(): void { public componentWillMount(): void {
//debugger; //debugger;
this.svc.loadData(this.props.showHiddenLists, this.props.showCatalogs, this.props.aadHttpClient, false) this.svc.loadData(this.props.showHiddenLists, this.props.showCatalogs, this.props.aadHttpClient, false)
.then((response) => { .then((response) => {
const state: ISpSecurityState = { const state: ISpSecurityState = {
securityInfo: response, securityInfo: response,
// permission: this.props.permission, // permission: this.props.permission,
selectedPermissions: this.props.selectedPermissions ? this.props.selectedPermissions : [], selectedPermissions: this.props.selectedPermissions ? this.props.selectedPermissions : [],
showUserPanel: false, showUserPanel: false,
showListPanel: false, showListPanel: false,
showPermissionsPanel: false, showPermissionsPanel: false,
showEmail: this.props.showEmail, showEmail: this.props.showEmail,
securityInfoLoaded: true, securityInfoLoaded: true,
errors:[] errors: []
}; };
// inlclude\exclude lists selected in property pane // inlclude\exclude lists selected in property pane
//debugger; //debugger;
state.securityInfo.lists = state.securityInfo.lists.filter((list) => { state.securityInfo.lists = state.securityInfo.lists.filter((list) => {
if (this.props.includeAdminSelectedLists) { // include the lists if (this.props.includeAdminSelectedLists) { // include the lists
if (find(this.props.adminSelectedLists, (asl) => { return list.id === asl; })) { if (find(this.props.adminSelectedLists, (asl) => { return list.id === asl; })) {
return true; return true;
} else { } else {
return false; return false;
} }
} else { // exclude the lists } else { // exclude the lists
if (find(this.props.adminSelectedLists, (asl) => { return list.id === asl; })) { if (find(this.props.adminSelectedLists, (asl) => { return list.id === asl; })) {
return false; return false;
} }
else { else {
return true; return true;
} }
} }
});
this.setState(state);
}).catch((errors: Array<string>) => {
this.setState((current) => ({ ...current, errors: errors, securityInfoLoaded: true }))
//debugger;
}); });
this.setState(state);
}).catch((errors:Array<string>) => {
this.setState((current)=>({...current,errors:errors,securityInfoLoaded:true}))
//debugger;
});
} }
public expandList(item: any): any { public expandList(item: any): any {
if (item instanceof SPListItem && !item.serverRelativeUrl) { // its a listitem. nothing to do if (item instanceof SPListItem && !item.serverRelativeUrl) { // its a listitem. nothing to do
@ -156,9 +158,9 @@ export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSec
this.setState(this.state); this.setState(this.state);
}).catch((error) => { }).catch((error) => {
let errors=this.state.errors; let errors = this.state.errors;
errors.push(`There was an error fetching site users -- ${error.message}`); errors.push(`There was an error fetching site users -- ${error.message}`);
this.setState((current)=>({...current,errors:errors})) this.setState((current) => ({ ...current, errors: errors }))
}); });
} }
@ -203,44 +205,38 @@ export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSec
public renderItemTitle(item?: any, index?: number, column?: IColumn): any { public renderItemTitle(item?: any, index?: number, column?: IColumn): any {
const extension = item.title.split('.').pop(); const extension = item.title.split('.').pop();
const isValidExtension: boolean = (this.validBrandIcons.indexOf(" " + extension + " ") !== -1); debugger;
const classname = css("ms-u-smOffset" + (item.level), isValidExtension ? const style = { marginLeft: item.level * 20 + 'px' }
`ms-Icon ms-BrandIcon--${extension} ms-BrandIcon--icon16`: return (
`ms-Icon ms-Icon--TextDocument ${styles.themecolor}`); <div className={styles.itemTitle} style={style}>
<Icon {...getFileTypeIconProps({ extension: extension, size: 16 })} />
return (
<div className={styles.itemTitle} >
<div className={classname} />
<span>&nbsp;{item.title}</span> <span>&nbsp;{item.title}</span>
</div>); </div>);
} }
public renderListTitle(item?: any, index?: number, column?: IColumn): any { public renderListTitle(item?: any, index?: number, column?: IColumn): any {
const iconName = item.itemCount > 0 ?
'FabricFormLibrary' :
'FabricFolder';
return (
<div className={styles.itemTitle} onClick={(e) => {
this.expandCollapseList(item);
}}>
<Icon iconName={iconName} className={styles.themecolor} />
<span >&nbsp;{item.title}</span>
</div>);
}
const classname = css("ms-Icon", styles.themecolor, item.itemCount > 0 ? public renderFolderTitle(item?: any, index?: number, column?: IColumn): any {
'ms-Icon ms-Icon--FabricFormLibrary': const style = { marginLeft: item.level * 20 + 'px' }
'ms-Icon ms-Icon--FabricFolder'); const iconName = item.itemCount > 0 ?
'FabricFormLibrary' :
'FabricFolder';
return ( return (
<div className={styles.itemTitle} onClick={(e) => { <div className={styles.itemTitle} onClick={(e) => {
//debugger;
this.expandCollapseList(item); this.expandCollapseList(item);
}}> }}>
<div className={classname} /> <Icon iconName={iconName} style={style} className={styles.themecolor} />
<span >&nbsp;{item.title}</span>
</div>);
}
public renderFolderTitle(item?: any, index?: number, column?: IColumn): any {
const classname = css("ms-u-smOffset" + (item.level),styles.themecolor, item.itemCount > 0 ?
'ms-Icon ms-Icon--FabricFormLibrary':
'ms-Icon ms-Icon--FabricFolder');
return (
<div className={styles.itemTitle} onClick={(e) => {
this.expandCollapseList(item);
}}>
<div className={classname} />
<span >&nbsp;{item.title}</span> <span >&nbsp;{item.title}</span>
</div>); </div>);
} }
@ -258,7 +254,7 @@ export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSec
} }
public renderUserItem(item: any, index: number, column: IColumn,effectivePermissions:ISelectedPermission[]): any { public renderUserItem(item: any, index: number, column: IColumn, effectivePermissions: ISelectedPermission[]): any {
let user: SPSiteUser = find(this.state.securityInfo.siteUsers, (su) => { let user: SPSiteUser = find(this.state.securityInfo.siteUsers, (su) => {
return su.id.toString() === column.key; return su.id.toString() === column.key;
@ -290,7 +286,7 @@ export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSec
) )
} }
public addUserColumns(columns: IColumn[], users: SPSiteUser[],effectivePermissions:ISelectedPermission[]): IColumn[] { public addUserColumns(columns: IColumn[], users: SPSiteUser[], effectivePermissions: ISelectedPermission[]): IColumn[] {
for (let user of users) { for (let user of users) {
if (user.isSelected) { if (user.isSelected) {
if ( if (
@ -305,9 +301,9 @@ export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSec
fieldName: "", fieldName: "",
minWidth: 20, minWidth: 20,
maxWidth: 20, maxWidth: 20,
onRender: (item?: any, index?: number, column?: IColumn)=>{ onRender: (item?: any, index?: number, column?: IColumn) => {
//debugger; //debugger;
return this.renderUserItem(item,index,column,effectivePermissions); return this.renderUserItem(item, index, column, effectivePermissions);
}, },
headerClassName: styles.rotatedColumnHeader, headerClassName: styles.rotatedColumnHeader,
@ -496,7 +492,7 @@ export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSec
}] }]
} }
}); });
let effectivePermissions=this.state.selectedPermissions.filter((sp)=>{ return sp.isChecked;}) let effectivePermissions = this.state.selectedPermissions.filter((sp) => { return sp.isChecked; })
let columns: Array<IColumn> = [ let columns: Array<IColumn> = [
{ {
key: "title", name: "Title", isResizable: true, fieldName: "title", key: "title", name: "Title", isResizable: true, fieldName: "title",
@ -504,7 +500,7 @@ export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSec
onRender: this.renderTitle, isRowHeader: true onRender: this.renderTitle, isRowHeader: true
}, },
]; ];
let displayColumns: IColumn[] = this.addUserColumns(columns, this.state.securityInfo.siteUsers,effectivePermissions); let displayColumns: IColumn[] = this.addUserColumns(columns, this.state.securityInfo.siteUsers, effectivePermissions);
let displayItems: (SPList | SPListItem)[] = filter(this.state.securityInfo.lists, (item) => { let displayItems: (SPList | SPListItem)[] = filter(this.state.securityInfo.lists, (item) => {
@ -515,9 +511,9 @@ export default class SpSecurity extends React.Component<ISpSecurityProps, ISpSec
) )
}) })
let errorMessages=[]; let errorMessages = [];
for (let error of this.state.errors){ for (let error of this.state.errors) {
errorMessages.push(<li>{error}</li>) errorMessages.push(<li>{error}</li>)
} }
return ( return (