diff --git a/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/SpSiteErDiagram.tsx b/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/SpSiteErDiagram.tsx index 29b44cfe0..7b64cbcd6 100644 --- a/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/SpSiteErDiagram.tsx +++ b/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/SpSiteErDiagram.tsx @@ -7,19 +7,22 @@ import { initDiagram } from './helpers/GoJSHelper'; import getGoJSNodesFromSPSiteData from './helpers/SPSiteDataToGoJSER'; interface SpSiteDiagramState { - nodeDataArray: any, - linkDataArray: any + loadingProgress: number, + nodeDataArray: any[], + linkDataArray: any[] } export default class SpSiteErDiagram extends React.Component { constructor(props: any) { super(props); - this.state = {nodeDataArray: [], linkDataArray: []}; + this.state = { loadingProgress: 0, nodeDataArray: [], linkDataArray: []}; } public async componentDidMount() { // Get SP SiteData for ER Diagram - let spSiteData = await getSPSiteData(this.props.context); + let spSiteData = await getSPSiteData(this.props.context, true, (progress) => { + this.setState({ loadingProgress: progress }); + }); // Transform to GoJS Model let goJSNodes = getGoJSNodesFromSPSiteData(spSiteData); // Set State @@ -29,13 +32,15 @@ export default class SpSiteErDiagram extends React.Component { return (
+ {this.state.loadingProgress != 100 || this.state.nodeDataArray.length == 0 ? +
Loading ({this.state.loadingProgress}%)
: + />}
); } diff --git a/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/helpers/SPSiteData.ts b/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/helpers/SPSiteData.ts index 6125afb86..9f9fa283d 100644 --- a/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/helpers/SPSiteData.ts +++ b/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/helpers/SPSiteData.ts @@ -7,10 +7,10 @@ import "@pnp/sp/lists/web"; import "@pnp/sp/fields"; export interface SPSiteData { - tables: SPTables[], - relations: SPRelations[] + tables: SPTable[], + relations: SPRelation[] } -export interface SPTables { +export interface SPTable { title: string, fields: SPTableField[], alerts: SPTableAlert[] @@ -25,15 +25,23 @@ export interface SPTableAlert { type: "Warning" | "Error", title: string, } -export interface SPRelations { +export interface SPRelation { fromTableTitle: string, toTableTitle: string, fromX: number | "n", toX: number | "m" } const storageKeyPrefix = "reactpnpjsdiagram_sitegraphdata_" -const getSPSiteData = async (spfxContext: any) : Promise => { +const getSPSiteData = async (spfxContext: any, force?: boolean, progress?: (number: number) => void) : Promise => { + // return from cache + let spSiteDataFromCache = JSON.parse(localStorage.getItem(storageKeyPrefix)); + if (spSiteDataFromCache && !force) { + progress(100); + return spSiteDataFromCache; + } + + // Load from site let spSiteData: SPSiteData = { relations: [], tables: [] @@ -43,14 +51,19 @@ const getSPSiteData = async (spfxContext: any) : Promise => { const sp = spfi().using(SPFx(spfxContext)); let lists = await sp.web.lists.filter("Hidden ne 1")(); + const totalCount = lists.filter(l => !l.Hidden).length; + let loadedCount = 0; + for(let list of lists) { if(!list.Hidden) { + loadedCount++; + progress && progress(loadedCount/totalCount * 100); // save names for later tmp_listNames[`{${list.Id}}`] = list.Title; // Tables/Lists - let table: SPTables = { title: list.Title, fields: [], alerts: [] }; + let table: SPTable = { title: list.Title, fields: [], alerts: [] }; // Fields let fields = (await sp.web.lists.getById(list.Id).fields.filter("Hidden ne 1")()) .filter(f => !f.Hidden).sort((a,b) => a.InternalName.charCodeAt(0) - b.InternalName.charCodeAt(0) ); @@ -66,13 +79,13 @@ const getSPSiteData = async (spfxContext: any) : Promise => { spSiteData.tables.push(table); // Links/Lookups - let relations: SPRelations[] = fields.filter(f => f.TypeDisplayName == "Lookup" && + let relations: SPRelation[] = fields.filter(f => f.TypeDisplayName == "Lookup" && (f as any).IsRelationship && (f as any).LookupList != '' && (f as any).LookupList != "AppPrincipals" - ).map(f => + ).map(f => {return { - fromTableTitle: f.Title, + fromTableTitle: list.Title, toTableTitle: (f as any).LookupList!, fromX: "n", toX: 1 @@ -83,10 +96,12 @@ const getSPSiteData = async (spfxContext: any) : Promise => { } // resolve Ids - spSiteData.relations = spSiteData.relations.map((r) => {return {...r, to: tmp_listNames[r.toTableTitle]}}) + spSiteData.relations = spSiteData.relations.map((r) => {return {...r, toTableTitle: tmp_listNames[r.toTableTitle]}}) console.log("SPSiteData", spSiteData); + localStorage.setItem(storageKeyPrefix, JSON.stringify(spSiteData)); + return spSiteData } diff --git a/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/helpers/SPSiteDataToGoJSER.ts b/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/helpers/SPSiteDataToGoJSER.ts index 44a50f2c8..b78dd43eb 100644 --- a/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/helpers/SPSiteDataToGoJSER.ts +++ b/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/helpers/SPSiteDataToGoJSER.ts @@ -40,7 +40,8 @@ const getGoJSNodesFromSPSiteData = (spSiteData: SPSiteData) : { nodeDataArray: [ linkDataArray = spSiteData.relations.map(r => { return { from: r.fromTableTitle, to: r.toTableTitle, - text: r.fromX+":"+r.toX + text: r.fromX+":"+r.toX, + toText: "1" }}) return { nodeDataArray, linkDataArray}