From 027fcb2147f6453e39634b102c0cfb786af31962 Mon Sep 17 00:00:00 2001 From: NiklasWilhelm Date: Mon, 3 Oct 2022 18:50:15 +0200 Subject: [PATCH] added layer --- .../components/SpSiteErDiagram.tsx | 21 ++- .../components/helpers/SPSiteData.ts | 144 +++++++++--------- .../components/helpers/SPSiteDataToGoJSER.ts | 48 ++++++ 3 files changed, 132 insertions(+), 81 deletions(-) create mode 100644 samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/helpers/SPSiteDataToGoJSER.ts 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 f2ac491ea..29b44cfe0 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 @@ -2,8 +2,9 @@ import * as React from 'react'; import styles from './SpSiteErDiagram.module.scss'; import { ISpSiteErDiagramProps } from './ISpSiteErDiagramProps'; import { ReactDiagram } from 'gojs-react'; -import getSiteData from './helpers/SPSiteData'; +import getSPSiteData from './helpers/SPSiteData'; import { initDiagram } from './helpers/GoJSHelper'; +import getGoJSNodesFromSPSiteData from './helpers/SPSiteDataToGoJSER'; interface SpSiteDiagramState { nodeDataArray: any, @@ -17,21 +18,17 @@ export default class SpSiteErDiagram extends React.Component { - const { - description, - isDarkTheme, - environmentMessage, - hasTeamsContext, - userDisplayName - } = this.props; - return ( -
+
{ - - let isLookup = (f as any).TypeDisplayName == "Lookup" && (f as any).IsRelationship; - - return { - name: f.InternalName, - iskey: false, - figure: "Decision", - color: isLookup ? colors.orange : colors.purple - }; +export interface SPTableField { + name: string, + displayName: string, + iskey: boolean, + type: string } +export interface SPTableAlert { + type: "Warning" | "Error", + title: string, +} +export interface SPRelations { + fromTableTitle: string, + toTableTitle: string, + fromX: number | "n", + toX: number | "m" +} +const storageKeyPrefix = "reactpnpjsdiagram_sitegraphdata_" +const getSPSiteData = async (spfxContext: any) : Promise => { - - -const getSiteData = async (spfxContext: any) => { - - let nodeDataArray: any = []; - let linkDataArray: any = []; - let listNames: any = {}; - - const sp = spfi().using(SPFx(spfxContext)); //.using(Caching({ store: "local" })); - let lists = await sp.web.lists.filter("Hidden ne 1").using(CacheKey(storageKeyPrefix+"lists"))(); - //lists = lists.slice(0,15); - - for(let list of lists) { - if(!list.Hidden) { - - listNames[`{${list.Id}}`] = list.Title; - - // Tables/Lists - let node = { key: list.Title, items: [] as any }; - let fields = (await sp.web.lists.getById(list.Id).fields.filter("Hidden ne 1").using(CacheKey(storageKeyPrefix+"fields_"+list.Id))()) - .filter(f => !f.Hidden).sort((a,b) => a.InternalName.charCodeAt(0) - b.InternalName.charCodeAt(0) ); - node.items = fields.map(f => {return getNodeFromField(f) }); - nodeDataArray.push(node); - - // Links/Lookups - let links = fields.filter(f => f.TypeDisplayName == "Lookup" && - (f as any).IsRelationship && - (f as any).LookupList != '' && - (f as any).LookupList != "AppPrincipals" - ).map(f => - {return { from: list.Title, to: (f as any).LookupList!, text: "0..N", toText: "1" }}); - linkDataArray= [...linkDataArray, ...links]; - + let spSiteData: SPSiteData = { + relations: [], + tables: [] } - } + let tmp_listNames: any = {}; - linkDataArray = linkDataArray.map((l: any) => {return {...l, to: listNames[l.to]}}) + const sp = spfi().using(SPFx(spfxContext)); + let lists = await sp.web.lists.filter("Hidden ne 1")(); - console.log("listNames", listNames); - console.log("nodeDataArray", nodeDataArray); - console.log("linkDataArray", linkDataArray); + for(let list of lists) { + if(!list.Hidden) { - return {nodeDataArray: nodeDataArray, linkDataArray: linkDataArray} + // save names for later + tmp_listNames[`{${list.Id}}`] = list.Title; + + // Tables/Lists + let table: SPTables = { 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) ); + table.fields = fields.map(f => { + return { + name: f.InternalName, + displayName: f.Title, + iskey: (f as any).TypeDisplayName == "Lookup" && (f as any).IsRelationship, + type: f.TypeDisplayName + } + }); + // add Table + spSiteData.tables.push(table); + + // Links/Lookups + let relations: SPRelations[] = fields.filter(f => f.TypeDisplayName == "Lookup" && + (f as any).IsRelationship && + (f as any).LookupList != '' && + (f as any).LookupList != "AppPrincipals" + ).map(f => + {return { + fromTableTitle: f.Title, + toTableTitle: (f as any).LookupList!, + fromX: "n", + toX: 1 + }}); + + spSiteData.relations = [...spSiteData.relations, ...relations]; + } + } + + // resolve Ids + spSiteData.relations = spSiteData.relations.map((r) => {return {...r, to: tmp_listNames[r.toTableTitle]}}) + + console.log("SPSiteData", spSiteData); + + return spSiteData } -export default getSiteData; \ No newline at end of file +export default getSPSiteData; \ No newline at end of file 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 new file mode 100644 index 000000000..44a50f2c8 --- /dev/null +++ b/samples/react-pnpjs-spsite-er-diagram/src/webparts/spSiteErDiagram/components/helpers/SPSiteDataToGoJSER.ts @@ -0,0 +1,48 @@ +import { List } from "@pnp/sp/lists"; +import { SPSiteData, SPTableField } from "./SPSiteData"; + + +const colors = { + 'red': '#be4b15', + 'green': '#52ce60', + 'blue': '#6ea5f8', + 'lightred': '#fd8852', + 'lightblue': '#afd4fe', + 'lightgreen': '#b9e986', + 'pink': '#faadc1', + 'purple': '#d689ff', + 'orange': '#fdb400', +} +const colorByType: any = { + 'Lookup': colors.orange +} + +const getNodeFromField = (f: SPTableField) => { + let isLookup = (f as any).TypeDisplayName == "Lookup" && (f as any).IsRelationship; + return { + name: f.name, + iskey: false, + figure: "Decision", + color: isLookup ? colors.orange : colors.purple + }; +} + +const getGoJSNodesFromSPSiteData = (spSiteData: SPSiteData) : { nodeDataArray: [], linkDataArray: [] } => { + + let nodeDataArray: any = []; + let linkDataArray: any = []; + + nodeDataArray = spSiteData.tables.map(t => { return { + key: t.title, + items: t.fields.map(f => getNodeFromField(f)) + }}) + + linkDataArray = spSiteData.relations.map(r => { return { + from: r.fromTableTitle, + to: r.toTableTitle, + text: r.fromX+":"+r.toX + }}) + + return { nodeDataArray, linkDataArray} +} +export default getGoJSNodesFromSPSiteData; \ No newline at end of file