Merge pull request #2110 from a1mery/app-secret-expiration-groupViews
[react-graph-secret-expiration] - Add group view options
This commit is contained in:
commit
1c77ae3b21
|
@ -35,3 +35,5 @@ obj
|
|||
packages/
|
||||
samples/react-teams-send-notification/MyNotes.md
|
||||
samples/react-teams-send-notification/teams/teams.zip
|
||||
samples/react-find-parker/release/component-dependency-audit/react-find-parker.json
|
||||
samples/react-find-parker/release/webpack-stats/react-find-parker.stats.json
|
||||
|
|
|
@ -33,6 +33,7 @@ Version|Date|Comments
|
|||
-------|----|--------
|
||||
1.0|September 17, 2021|Initial release
|
||||
1.1|October 10, 2021|Add pagination
|
||||
1.2|November 04, 2021|Add group views
|
||||
|
||||
|
||||
## Minimal Path to Awesome
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 64 MiB After Width: | Height: | Size: 18 MiB |
|
@ -9,7 +9,7 @@
|
|||
"This sample web part shows the list of your applications registered in Azure AD along with their associated client secret/certificate expiration date."
|
||||
],
|
||||
"creationDateTime": "2021-09-17",
|
||||
"updateDateTime": "2021-10-10",
|
||||
"updateDateTime": "2021-11-04",
|
||||
"products": [
|
||||
"SharePoint",
|
||||
"Office"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"solution": {
|
||||
"name": "react-graph-app-secret-expiration-client-side-solution",
|
||||
"id": "b25d85a4-7310-408a-a263-25959b0a5b1b",
|
||||
"version": "1.1.0.0",
|
||||
"version": "1.2.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
"isDomainIsolated": false,
|
||||
"skipFeatureDeployment": true,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "react-graph-app-secret-expiration",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "react-graph-app-secret-expiration",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"private": true,
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
|
|
|
@ -12,7 +12,7 @@ export interface IApplication {
|
|||
export interface IPasswordCredential {
|
||||
customKeyIdentifier: string;
|
||||
displayName: string;
|
||||
endDateTime: Date;
|
||||
endDateTime: string;
|
||||
hint: string;
|
||||
keyId: string;
|
||||
secretText: string;
|
||||
|
@ -22,7 +22,7 @@ export interface IPasswordCredential {
|
|||
export interface IKeyCredential {
|
||||
customKeyIdentifier: string;
|
||||
displayName: string;
|
||||
endDateTime: Date;
|
||||
endDateTime: string;
|
||||
key: string;
|
||||
keyId: string;
|
||||
startDateTime: string;
|
||||
|
@ -37,4 +37,5 @@ export interface IFormattedApplication {
|
|||
daysLeft: number;
|
||||
type: string;
|
||||
expirationDate: string;
|
||||
linkTitle: string;
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
{
|
||||
"applications": [
|
||||
{
|
||||
"appId": "bb4bcecc-d0cb-478a-9d48-1527cb7b65c0",
|
||||
"displayName": "API Backend",
|
||||
"keyCredentials": [],
|
||||
"passwordCredentials": [
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Password friendly name",
|
||||
"endDateTime": "2020-09-20T15:47:46.5876682Z",
|
||||
"hint": "42",
|
||||
"keyId": "c2435363-4f50-4c14-8994-0122e77d84c9",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-09-20T15:47:46.5876682Z"
|
||||
},
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Postman",
|
||||
"endDateTime": "2021-11-25T16:25:17.375Z",
|
||||
"hint": "42",
|
||||
"keyId": "7ead14df-56e8-4a24-9f6e-6692ae17e84f",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-09-20T15:25:17.375Z"
|
||||
},
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "PnP",
|
||||
"endDateTime": "2022-02-04T06:58:04.525Z",
|
||||
"hint": "42",
|
||||
"keyId": "8fc28fb8-ab39-4623-bd75-6d7baf5f205d",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-02-04T06:58:17.678Z"
|
||||
},
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Dev",
|
||||
"endDateTime": "2021-12-15T16:36:58.443Z",
|
||||
"hint": "42",
|
||||
"keyId": "ef77eda1-741c-4b51-9de7-aa455831dff0",
|
||||
"secretText": null,
|
||||
"startDateTime": "2020-12-15T16:37:05.242Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"appId": "8537b74d-1bfe-41ba-849a-eb25917d3746",
|
||||
"displayName": "Client API",
|
||||
"keyCredentials": [],
|
||||
"passwordCredentials": [
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Password friendly name",
|
||||
"endDateTime": "2022-09-20T15:47:46.5876682Z",
|
||||
"hint": "42",
|
||||
"keyId": "7e6dd1c3-2366-4c5a-9a3f-d1c83f40ba11",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-09-20T15:47:46.5876682Z"
|
||||
},
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Password friendly name",
|
||||
"endDateTime": "2021-12-05T15:47:46.5876682Z",
|
||||
"hint": "42",
|
||||
"keyId": "7c341ab9-089e-47e1-946b-60b155c3e94c",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-09-20T15:47:46.5876682Z"
|
||||
},
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Password friendly name",
|
||||
"endDateTime": "2021-12-01T15:47:46.5876682Z",
|
||||
"hint": "42",
|
||||
"keyId": "24d724d8-71b3-471e-9b92-a5bd7e9bb6d6",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-09-20T15:47:46.5876682Z"
|
||||
},
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Password friendly name",
|
||||
"endDateTime": "2021-11-20T15:47:46.5876682Z",
|
||||
"hint": "42",
|
||||
"keyId": "4488b5fa-01a0-4191-a96e-de3a83cae203",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-11-20T15:47:46.5876682Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"appId": "e2bfaff8-9a03-4837-886e-b110b4972a47",
|
||||
"displayName": "Graph Console App",
|
||||
"keyCredentials": [],
|
||||
"passwordCredentials": [
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Password friendly name",
|
||||
"endDateTime": "2021-12-28T15:47:46.5876682Z",
|
||||
"hint": "42",
|
||||
"keyId": "7791e9be-defd-4588-9612-ea6404af1875",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-09-20T15:47:46.5876682Z"
|
||||
},
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Password friendly name",
|
||||
"endDateTime": "2022-01-03T15:47:46.5876682Z",
|
||||
"hint": "42",
|
||||
"keyId": "8962ac05-6a3e-4f9a-b91f-e0212cd9847b",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-09-20T15:47:46.5876682Z"
|
||||
},
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Password friendly name",
|
||||
"endDateTime": "2022-11-18T15:47:46.5876682Z",
|
||||
"hint": "42",
|
||||
"keyId": "85bc5551-1165-4e04-aa77-0d0c8f32ab1f",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-09-20T15:47:46.5876682Z"
|
||||
},
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Password friendly name",
|
||||
"endDateTime": "2020-12-28T15:47:46.5876682Z",
|
||||
"hint": "42",
|
||||
"keyId": "cd909eca-bc21-4005-b346-7e2ef47fe26b",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-09-20T15:47:46.5876682Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"appId": "b166b3ca-38e0-4dd5-80e4-03f51509a8eb",
|
||||
"displayName": "PnP Modernization Scanner",
|
||||
"keyCredentials": [
|
||||
{
|
||||
"customKeyIdentifier": "SampleId",
|
||||
"displayName": "PnP Modernization Scanner",
|
||||
"endDateTime": "2031-01-11T23:00:00Z",
|
||||
"key": "SampleKey",
|
||||
"keyId": "9942dd18-a265-422f-bbfe-b8fdd866c3d3",
|
||||
"startDateTime": "2021-01-11T23:00:00Z",
|
||||
"type": "AsymmetricX509Cert",
|
||||
"usage": "Verify"
|
||||
}
|
||||
],
|
||||
"passwordCredentials": []
|
||||
},
|
||||
{
|
||||
"appId": "14ce9f15-41ed-446b-8733-a0eeb1379b38",
|
||||
"displayName": "Bot - OfficeDev",
|
||||
"keyCredentials": [],
|
||||
"passwordCredentials": [
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Password friendly name",
|
||||
"endDateTime": "2023-09-20T15:47:46.5876682Z",
|
||||
"hint": "42",
|
||||
"keyId": "cb8cf8ec-630b-4da6-a578-4d27742d069c",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-09-20T15:47:46.5876682Z"
|
||||
},
|
||||
{
|
||||
"customKeyIdentifier": null,
|
||||
"displayName": "Password friendly name",
|
||||
"endDateTime": "2024-09-20T15:47:46.5876682Z",
|
||||
"hint": "42",
|
||||
"keyId": "2bfdc738-db27-4b3d-898d-ce3f57ab81eb",
|
||||
"secretText": null,
|
||||
"startDateTime": "2021-09-20T15:47:46.5876682Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -3,7 +3,9 @@ import * as ReactDom from 'react-dom';
|
|||
import { Version } from '@microsoft/sp-core-library';
|
||||
import {
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField
|
||||
IPropertyPaneDropdownOption,
|
||||
PropertyPaneDropdown,
|
||||
PropertyPaneToggle
|
||||
} from '@microsoft/sp-property-pane';
|
||||
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
|
||||
|
||||
|
@ -13,11 +15,18 @@ import { IGraphAppSecretExpirationProps } from './components/IGraphAppSecretExpi
|
|||
import { MSGraphClient } from '@microsoft/sp-http';
|
||||
|
||||
export interface IGraphAppSecretExpirationWebPartProps {
|
||||
description: string;
|
||||
groupByColumn: string;
|
||||
expiringSoon: boolean;
|
||||
displaySampleData: boolean;
|
||||
|
||||
}
|
||||
|
||||
export default class GraphAppSecretExpirationWebPart extends BaseClientSideWebPart<IGraphAppSecretExpirationWebPartProps> {
|
||||
private graphClient: MSGraphClient;
|
||||
private dropdownOptions: IPropertyPaneDropdownOption[] = [
|
||||
{ key: "none", text: "None" },
|
||||
{ key: "applicationId", text: "Application ID" },
|
||||
{ key: "type", text: "Type" }];
|
||||
|
||||
public onInit(): Promise<void> {
|
||||
return new Promise<void>((resolve: () => void, reject: (error: any) => void): void => {
|
||||
|
@ -34,8 +43,10 @@ export default class GraphAppSecretExpirationWebPart extends BaseClientSideWebPa
|
|||
const element: React.ReactElement<IGraphAppSecretExpirationProps> = React.createElement(
|
||||
GraphAppSecretExpiration,
|
||||
{
|
||||
description: this.properties.description,
|
||||
graphClient: this.graphClient
|
||||
graphClient: this.graphClient,
|
||||
groupByColumn: this.properties.groupByColumn,
|
||||
expiringSoon: this.properties.expiringSoon,
|
||||
displaySampleData: this.properties.displaySampleData
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -61,8 +72,27 @@ export default class GraphAppSecretExpirationWebPart extends BaseClientSideWebPa
|
|||
{
|
||||
groupName: strings.BasicGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneTextField('description', {
|
||||
label: strings.DescriptionFieldLabel
|
||||
PropertyPaneDropdown('groupByColumn', {
|
||||
label: strings.DefaultGroupColumnFieldLabel,
|
||||
options: this.dropdownOptions,
|
||||
selectedKey: "none"
|
||||
}),
|
||||
PropertyPaneToggle('expiringSoon', {
|
||||
label: strings.DisplayOnlySecretsFieldLabel,
|
||||
onText: "Yes",
|
||||
offText: "No"
|
||||
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
groupName: strings.OtherGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneToggle('displaySampleData', {
|
||||
label: strings.DisplaySampleDataFieldLabel,
|
||||
onText: "Yes",
|
||||
offText: "No"
|
||||
|
||||
})
|
||||
]
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
.container {
|
||||
max-width: 900px;
|
||||
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);
|
||||
border: 1px solid lightgray
|
||||
//box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.row {
|
||||
|
|
|
@ -5,9 +5,10 @@ import { ListView, IViewField, SelectionMode, GroupOrder, IGrouping } from "@pnp
|
|||
import { IApplications, IApplication, IFormattedApplication } from '../../../models/IApplication';
|
||||
import { IGraphAppSecretExpirationState } from './GraphAppSecretExpirationState';
|
||||
import * as moment from 'moment';
|
||||
import { DefaultButton, Spinner, mergeStyles, SearchBox } from '@fluentui/react';
|
||||
import { Spinner, mergeStyles, SearchBox } from '@fluentui/react';
|
||||
import { Pagination } from "@pnp/spfx-controls-react/lib/pagination";
|
||||
import * as strings from 'GraphAppSecretExpirationWebPartStrings';
|
||||
import sampleApplications from '../../../models/SampleApplications.json';
|
||||
|
||||
const stackItemHidden = mergeStyles({
|
||||
display: 'none',
|
||||
|
@ -16,7 +17,8 @@ const _viewFields: IViewField[] = [
|
|||
{
|
||||
name: "applicationId",
|
||||
displayName: "Application ID",
|
||||
minWidth: 250
|
||||
minWidth: 250,
|
||||
linkPropertyName: "linkTitle"
|
||||
},
|
||||
{
|
||||
name: "displayName",
|
||||
|
@ -71,7 +73,12 @@ export default class GraphAppSecretExpiration extends React.Component<IGraphAppS
|
|||
|
||||
|
||||
public componentDidMount(): void {
|
||||
this._getApplications();
|
||||
if (!this.props.displaySampleData) {
|
||||
this._getApplications();
|
||||
} else {
|
||||
this._propertiesMapping(sampleApplications.applications);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private _getApplications(): IApplication[] {
|
||||
|
@ -126,9 +133,16 @@ export default class GraphAppSecretExpiration extends React.Component<IGraphAppS
|
|||
displayName: app.displayName,
|
||||
type: "Secret",
|
||||
expirationDate: (moment(pswd.endDateTime)).format('DD-MMM-YYYY'),
|
||||
daysLeft: daysBeforeExpiration > 0 ? daysBeforeExpiration : 0
|
||||
daysLeft: daysBeforeExpiration > 0 ? daysBeforeExpiration : 0,
|
||||
linkTitle: "https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Credentials/appId/" + app.appId
|
||||
};
|
||||
displayedApplication.push(formatedApp);
|
||||
if (this.props.expiringSoon) {
|
||||
if (daysBeforeExpiration < 30) {
|
||||
displayedApplication.push(formatedApp);
|
||||
}
|
||||
} else {
|
||||
displayedApplication.push(formatedApp);
|
||||
}
|
||||
});
|
||||
app.keyCredentials.forEach(keyCred => {
|
||||
let daysBeforeExpiration = moment.duration((moment(keyCred.endDateTime)).diff(today, 'days'), 'days').asDays();
|
||||
|
@ -137,18 +151,27 @@ export default class GraphAppSecretExpiration extends React.Component<IGraphAppS
|
|||
displayName: app.displayName,
|
||||
type: "Certificate",
|
||||
expirationDate: (moment(keyCred.endDateTime)).format('DD-MMM-YYYY'),
|
||||
daysLeft: daysBeforeExpiration > 0 ? daysBeforeExpiration : 0
|
||||
daysLeft: daysBeforeExpiration > 0 ? daysBeforeExpiration : 0,
|
||||
linkTitle: "https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Credentials/appId/" + app.appId
|
||||
};
|
||||
displayedApplication.push(formatedApp);
|
||||
if (this.props.expiringSoon) {
|
||||
if (daysBeforeExpiration < 30) {
|
||||
displayedApplication.push(formatedApp);
|
||||
}
|
||||
} else {
|
||||
displayedApplication.push(formatedApp);
|
||||
}
|
||||
});
|
||||
});
|
||||
this.setState({
|
||||
applications: displayedApplication,
|
||||
filteredApplications: displayedApplication
|
||||
filteredApplications: displayedApplication,
|
||||
loading: false
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
this._groupView();
|
||||
}
|
||||
|
||||
private _getPage(selectedPage: number) {
|
||||
|
@ -194,10 +217,10 @@ export default class GraphAppSecretExpiration extends React.Component<IGraphAppS
|
|||
}
|
||||
|
||||
private _groupView = () => {
|
||||
if (this.state.groupByFields.length === 0) {
|
||||
if (this.props.groupByColumn !== "none") {
|
||||
let groupByFields: IGrouping[] = [
|
||||
{
|
||||
name: "applicationId",
|
||||
name: this.props.groupByColumn,
|
||||
order: GroupOrder.ascending
|
||||
}
|
||||
];
|
||||
|
@ -218,14 +241,13 @@ export default class GraphAppSecretExpiration extends React.Component<IGraphAppS
|
|||
<div className={styles.graphAppSecretExpiration}>
|
||||
<div className={styles.container}>
|
||||
<br />
|
||||
<p className={styles.title}>Application list :</p>
|
||||
<p className={styles.title}>Certificates and secrets :</p>
|
||||
<div className={this.state.loading ? "" : stackItemHidden}>
|
||||
<Spinner label="Loading..." ariaLive="assertive" labelPosition="left" />
|
||||
<br />
|
||||
</div>
|
||||
<div className={this.state.loading ? stackItemHidden : ""}>
|
||||
<DefaultButton text={this.state.groupByFields.length === 0 ? "Group by App ID" : "Ungroup"} onClick={this._groupView} />
|
||||
<SearchBox placeholder="Search" onChange={(e, text) => this._filterApplication(text, false)} onClear={() => this._filterApplication("", true)} value={this.state.filterValue} />
|
||||
<SearchBox placeholder="Search" onChange={(e, text) => this._filterApplication(text, true)} onClear={() => this._filterApplication("", false)} value={this.state.filterValue} />
|
||||
<ListView
|
||||
items={this.state.filteredApplications.slice(this.state.page === 1 || this.state.filterValue !== "" ? 0 : this.state.page * 10 - 10, this.state.page * 10)}
|
||||
viewFields={_viewFields}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { IGrouping } from '@pnp/spfx-controls-react/lib/ListView';
|
||||
import { IApplications, IApplication,IPasswordCredential,IKeyCredential,IFormattedApplication } from '../../../models/IApplication';
|
||||
import { IFormattedApplication } from '../../../models/IApplication';
|
||||
|
||||
export interface IGraphAppSecretExpirationState {
|
||||
applications: IFormattedApplication[];
|
||||
filteredApplications: IFormattedApplication[];
|
||||
filterValue: string;
|
||||
searchFilter: string;
|
||||
groupByFields: IGrouping[];
|
||||
page: number;
|
||||
error: string;
|
||||
loading: boolean;
|
||||
}
|
||||
applications: IFormattedApplication[];
|
||||
filteredApplications: IFormattedApplication[];
|
||||
filterValue: string;
|
||||
searchFilter: string;
|
||||
groupByFields: IGrouping[];
|
||||
page: number;
|
||||
error: string;
|
||||
loading: boolean;
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import { MSGraphClient } from "@microsoft/sp-http";
|
||||
|
||||
export interface IGraphAppSecretExpirationProps {
|
||||
description: string;
|
||||
graphClient: MSGraphClient;
|
||||
groupByColumn: string;
|
||||
expiringSoon: boolean;
|
||||
displaySampleData: boolean;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
define([], function() {
|
||||
define([], function () {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
"PropertyPaneDescription": "Displays list of all Azure AD applications secrets and certificates expiration date.",
|
||||
"BasicGroupName": "Display settings:",
|
||||
"OtherGroupName": "Other settings:",
|
||||
"DescriptionFieldLabel": "Description Field",
|
||||
"DisplayOnlySecretsFieldLabel": "Display only secrets/certificates that will expire soon:",
|
||||
"DisplaySampleDataFieldLabel": "Display sample data:",
|
||||
"DefaultGroupColumnFieldLabel": "Default group column:"
|
||||
}
|
||||
});
|
|
@ -1,7 +1,11 @@
|
|||
declare interface IGraphAppSecretExpirationWebPartStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
OtherGroupName: string;
|
||||
DescriptionFieldLabel: string;
|
||||
DisplayOnlySecretsFieldLabel: string;
|
||||
DisplaySampleDataFieldLabel: string;
|
||||
DefaultGroupColumnFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'GraphAppSecretExpirationWebPartStrings' {
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
"inlineSources": false,
|
||||
"strictNullChecks": false,
|
||||
"noUnusedLocals": false,
|
||||
"resolveJsonModule": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./node_modules/@microsoft"
|
||||
|
|
Loading…
Reference in New Issue