Merge pull request #1743 from petkir/petkir-react-tree-orgchartgraph

This commit is contained in:
Hugo Bernier 2021-02-28 16:09:21 -05:00 committed by GitHub
commit 60cd3649bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 717 additions and 358 deletions

View File

@ -3,15 +3,20 @@
## Summary ## Summary
The Tree Organization WebPart shows the Organization Chart of the or the team, the web part reads infomation from current user to build the Organization Chart. The Tree Organization WebPart shows the Organization Chart of the or the team, the web part reads infomation from current user to build the Organization Chart.
We can configure in the webpart properties if it show all Organization Chart or the only user team, (same manager and peers). You can configure in the webpart properties:
* show all Organization Chart
* the only user team, (same manager and peers).
* show Organization Chart by picking up user
![Organization Chart Web Part](./assets/react-tree-orgchart.gif)
![Organization Chart Web Part](./assets/Screenshot1.png) ![Organization Chart Web Part](./assets/Screenshot1.png)
![Organization Chart Web Part](./assets/Screenshot2.png) ![Organization Chart Web Part](./assets/Screenshot2.png)
![Organization Chart Web Part](./assets/Screenshot3.png) ![Organization Chart Web Part](./assets/Screenshot3.png)
## Used SharePoint Framework Version ## Used SharePoint Framework Version
![drop](https://img.shields.io/badge/version-1.10.0-green.svg) ![drop](https://img.shields.io/badge/version-1.10.0-green.svg)
@ -26,21 +31,34 @@ We can configure in the webpart properties if it show all Organization Chart or
Property |Type|Required| comments Property |Type|Required| comments
--------------------|----|--------|---------- --------------------|----|--------|----------
WebPart Title| Text| no| title | Text| no| WebPart Title
Show Only My Team| Boolean | true teamLeader |Text|no|UPN of manager if viewType is 4
MaxDepth | Number| yes | Maximum number of levels to show viewType|viewType(number)|yes|if currentUserTeam is set it's not required
maxLevels | Number| yes | Maximum number of levels to show
detailBehavoir |boolean|no|Delve or Live Persona Card
excludefilter|boolean|no|Filter contains/not contains
filter|string|no|Filter Value
currentUserTeam|boolean|no|only in Interface to handle previouse installations
### viewType Enum:
```
MyTeam = 1,
CompanyHierarchy = 2,
ShowOtherTeam = 4
```
## Solution ## Solution
Solution|Author(s) Solution|Author(s)
--------|--------- --------|---------
Tree Organization WebPart|João Mendes Tree Organization WebPart|João Mendes
Tree Organization WebPart|Peter Paul Kirschner ([@petkir_at](https://twitter.com/petkir_at))
## Version history ## Version history
Version|Date|Comments Version|Date|Comments
-------|----|-------- -------|----|--------
1.1.0|Feb 28, 2021|Added <ul><li>Show Other Team</li><li>Live Contact Card</li><li>Filter user by userPrincipalName</li><li>Graph API</li><li>PNPJS updates</li></ul>
1.0.2|June 12, 2020|Added exception handler for profiles missing display name 1.0.2|June 12, 2020|Added exception handler for profiles missing display name
1.0.1|Jan 28, 2020|Update to SPFx 1.10, minor fixes and refactoring. 1.0.1|Jan 28, 2020|Update to SPFx 1.10, minor fixes and refactoring.
1.0.0|Feb 25, 2019|Initial release 1.0.0|Feb 25, 2019|Initial release

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 MiB

View File

@ -3,7 +3,7 @@
"solution": { "solution": {
"name": "react-tree-orgchart-client-side-solution", "name": "react-tree-orgchart-client-side-solution",
"id": "d76a0c4f-d669-42eb-9533-68d5cec5e9d3", "id": "d76a0c4f-d669-42eb-9533-68d5cec5e9d3",
"version": "1.0.2.0", "version": "1.1.0.0",
"includeClientSideAssets": true, "includeClientSideAssets": true,
"skipFeatureDeployment": true, "skipFeatureDeployment": true,
"isDomainIsolated": false "isDomainIsolated": false

View File

@ -1,6 +1,6 @@
{ {
"name": "react-tree-orgchart", "name": "react-tree-orgchart",
"version": "0.0.1", "version": "1.0.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -2265,9 +2265,9 @@
} }
}, },
"@microsoft/microsoft-graph-types": { "@microsoft/microsoft-graph-types": {
"version": "1.5.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-1.5.0.tgz", "resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-1.7.0.tgz",
"integrity": "sha512-eit9LMlhHLyzCByATGL8d7izWNRVBlzrPMfXqy2a9qIVUUNIGxyqkGJNrpEh3EVDXW2r+/ASsBAqzHkm8zWJiQ==" "integrity": "sha512-Mxu5H+69F8T5NzV4+U8FkTvpIYYWHsmRZzfAuOlIO0zJJGlVyRIVqpq4NmOdUXGC00vZ73ONgCuzuaksxqDm/Q=="
}, },
"@microsoft/node-core-library": { "@microsoft/node-core-library": {
"version": "3.15.1", "version": "3.15.1",
@ -4013,12 +4013,12 @@
} }
}, },
"@pnp/common": { "@pnp/common": {
"version": "1.2.9", "version": "1.3.11",
"resolved": "https://registry.npmjs.org/@pnp/common/-/common-1.2.9.tgz", "resolved": "https://registry.npmjs.org/@pnp/common/-/common-1.3.11.tgz",
"integrity": "sha512-wVu8yJZvdnN99hhpmHxhK0HbUVMg61y8o8vC2w3MK+nql65GH9YaxkDQotNSKlYjDakzG/HYa8cZW3TIaCFPcg==", "integrity": "sha512-RhYKcfMP+h0pAzORZRHSPPLOBB58djN/pfnorpWPjsx6ZxMqbiDqTzAtTF4m8z/mdNnxJr0Q3kwt4ImU3FjwnA==",
"requires": { "requires": {
"adal-angular": "1.0.17", "adal-angular": "1.0.17",
"tslib": "1.9.3" "tslib": "1.10.0"
}, },
"dependencies": { "dependencies": {
"adal-angular": { "adal-angular": {
@ -4027,118 +4027,119 @@
"integrity": "sha1-bpNuDkH5HTsqiOf/ypwvb29WLMQ=" "integrity": "sha1-bpNuDkH5HTsqiOf/ypwvb29WLMQ="
}, },
"tslib": { "tslib": {
"version": "1.9.3", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
} }
} }
}, },
"@pnp/graph": { "@pnp/graph": {
"version": "1.2.9", "version": "1.3.11",
"resolved": "https://registry.npmjs.org/@pnp/graph/-/graph-1.2.9.tgz", "resolved": "https://registry.npmjs.org/@pnp/graph/-/graph-1.3.11.tgz",
"integrity": "sha512-n1aH2HWmXXc0ZRBTnU9U3oz5Vua7jzw+zjRhkdQYh+AAnBcVD2drT+CaAJNB9RND5SpzajJ31GR+0cmDx7J2qw==", "integrity": "sha512-AbJdiCdI+SZTk7LI0NP5snw8D0udQWQbFRhCmI1e+j6k/Wt/FYEfXkgiAqXKc+f8+PpUtt1/ezab3sbrxs9btA==",
"requires": { "requires": {
"@microsoft/microsoft-graph-types": "1.5.0", "@microsoft/microsoft-graph-types": "1.7.0",
"tslib": "1.9.3" "tslib": "1.10.0"
}, },
"dependencies": { "dependencies": {
"tslib": { "tslib": {
"version": "1.9.3", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
} }
} }
}, },
"@pnp/logging": { "@pnp/logging": {
"version": "1.2.9", "version": "1.3.11",
"resolved": "https://registry.npmjs.org/@pnp/logging/-/logging-1.2.9.tgz", "resolved": "https://registry.npmjs.org/@pnp/logging/-/logging-1.3.11.tgz",
"integrity": "sha512-JNxoHkPhPnnC1PHnU+wQVkDkaBzrskDvLHn7bq84Uz+ppZEnKp0IuOxvmkAPMwD1NVP5qRbbiBh7dIHu8b9rNw==", "integrity": "sha512-hADlIXwvF/wjee7425nFJ6NhqaWpWTJ5yg02bpwBUsiSuFqEUf+LwuAcyHQre2lMs6KyNa65FWoRQok9BlZuxA==",
"requires": { "requires": {
"tslib": "1.9.3" "tslib": "1.10.0"
}, },
"dependencies": { "dependencies": {
"tslib": { "tslib": {
"version": "1.9.3", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
} }
} }
}, },
"@pnp/odata": { "@pnp/odata": {
"version": "1.2.9", "version": "1.3.11",
"resolved": "https://registry.npmjs.org/@pnp/odata/-/odata-1.2.9.tgz", "resolved": "https://registry.npmjs.org/@pnp/odata/-/odata-1.3.11.tgz",
"integrity": "sha512-mE4bY5PQXxNYJIyh5Mgqda4AeX5DWEjT9NuUH7G05JOKwV51DbUX+UPIIy7AqBXDjo05S3QvOJw6+4OfeMQuZQ==", "integrity": "sha512-yMaRiuVZRei2pkryCOqsw3ZXD2Lw30IJv136WQmQPQPOxG4cvsS9+woXkfMqbWV2KQ1evFUqVXbitIz6eDVfNA==",
"requires": { "requires": {
"tslib": "1.9.3" "tslib": "1.10.0"
}, },
"dependencies": { "dependencies": {
"tslib": { "tslib": {
"version": "1.9.3", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
} }
} }
}, },
"@pnp/sp": { "@pnp/sp": {
"version": "1.2.9", "version": "1.3.11",
"resolved": "https://registry.npmjs.org/@pnp/sp/-/sp-1.2.9.tgz", "resolved": "https://registry.npmjs.org/@pnp/sp/-/sp-1.3.11.tgz",
"integrity": "sha512-O+V/IrI/dqDtc/d42HsTlPbqNqLut6/UiTkWwuZMwbhJeNmb9S/CyygTaa2luyvVw2UaVa1x70zdoslxU0Itew==", "integrity": "sha512-NjdeGe81aukiSPelSPjgAFRC1+SrNPTXvTdEqTH+Q1ZvgNtk8bdZp6K6xf9emfeM2qZDOu9GpKZpg0W/emq++g==",
"requires": { "requires": {
"tslib": "1.9.3" "tslib": "1.10.0"
}, },
"dependencies": { "dependencies": {
"tslib": { "tslib": {
"version": "1.9.3", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
} }
} }
}, },
"@pnp/sp-clientsvc": { "@pnp/sp-clientsvc": {
"version": "1.2.9", "version": "1.3.11",
"resolved": "https://registry.npmjs.org/@pnp/sp-clientsvc/-/sp-clientsvc-1.2.9.tgz", "resolved": "https://registry.npmjs.org/@pnp/sp-clientsvc/-/sp-clientsvc-1.3.11.tgz",
"integrity": "sha512-zaInYyQgbyk5a4+2KMr9qHRKHexqRQMiQk5eu6SM6fIEVyC5H422Tr5WREVzNTMp4YVl8MKuXkeTNxLhG7iTJQ==", "integrity": "sha512-eIUnmDWjizcWJzhWxAbfsxEyHF1dabkGlihnDnlcYGhtvh8BwuM67A57qc5fbxzCS59c0YU57szB1EucoNmV4A==",
"requires": { "requires": {
"tslib": "1.9.3" "tslib": "1.10.0"
}, },
"dependencies": { "dependencies": {
"tslib": { "tslib": {
"version": "1.9.3", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
} }
} }
}, },
"@pnp/sp-taxonomy": { "@pnp/sp-taxonomy": {
"version": "1.2.9", "version": "1.3.11",
"resolved": "https://registry.npmjs.org/@pnp/sp-taxonomy/-/sp-taxonomy-1.2.9.tgz", "resolved": "https://registry.npmjs.org/@pnp/sp-taxonomy/-/sp-taxonomy-1.3.11.tgz",
"integrity": "sha512-pJCuikAI2ntplc1VoyIo5wbe2F44t9B6sA66L7LqOPc/i+qU8ywjkelHznmshUomOzPycuFXqwgYcnHyxJVCXw==", "integrity": "sha512-shzCSjmOlr6mojCXJkfD8Xf9lJnhphq4Fj6mdUQGwpak+VIU+Fogf6AI0j6AReCKtKsKyqfud9X7C8tH07C3DA==",
"requires": { "requires": {
"tslib": "1.9.3" "tslib": "1.10.0"
}, },
"dependencies": { "dependencies": {
"tslib": { "tslib": {
"version": "1.9.3", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
} }
} }
}, },
"@pnp/spfx-controls-react": { "@pnp/spfx-controls-react": {
"version": "1.11.0", "version": "1.21.1",
"resolved": "https://registry.npmjs.org/@pnp/spfx-controls-react/-/spfx-controls-react-1.11.0.tgz", "resolved": "https://registry.npmjs.org/@pnp/spfx-controls-react/-/spfx-controls-react-1.21.1.tgz",
"integrity": "sha512-7i2g3l95/CXpiugfM8V0m8aEHeyoRFBlTiZfoQiue5LW9O3XC+okDSbf8vOBNgddYTRLnRZKEo/TMKcuNEi3zQ==", "integrity": "sha512-HpBZtrtNfAMn9vySTEZutFovnwiYGg7skptLhf2gZmhSOUIBB0THweBRTDPqT8zBSkxc1ffVHAOArVgaMb+zMQ==",
"requires": { "requires": {
"@pnp/common": "1.0.1", "@pnp/common": "1.0.1",
"@pnp/logging": "1.0.1", "@pnp/logging": "1.0.1",
"@pnp/odata": "1.0.1", "@pnp/odata": "1.0.1",
"@pnp/sp": "1.0.1", "@pnp/sp": "1.0.1",
"@pnp/telemetry-js": "1.0.0", "@pnp/telemetry-js": "2.0.0",
"@types/chart.js": "2.7.40", "@types/chart.js": "2.7.40",
"chart.js": "2.7.3", "chart.js": "2.7.3",
"color": "^3.1.0", "color": "^3.1.2",
"lodash": "4.17.4", "lodash": "4.17.13",
"office-ui-fabric-react": "5.131.0" "office-ui-fabric-react": "5.131.0",
"react-quill": "1.3.3"
}, },
"dependencies": { "dependencies": {
"@pnp/common": { "@pnp/common": {
@ -4173,35 +4174,30 @@
"tslib": "1.8.1" "tslib": "1.8.1"
} }
}, },
"color": { "@pnp/telemetry-js": {
"version": "3.1.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/color/-/color-3.1.0.tgz", "resolved": "https://registry.npmjs.org/@pnp/telemetry-js/-/telemetry-js-2.0.0.tgz",
"integrity": "sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg==", "integrity": "sha512-qFNm3mTerTnxgTR6c/4iMMt8EUKrQn5z0XG/IQtpNlp6m7KXRDFR87mQKeBVtSv2LhxGO0VNFndKJIibBw52zQ==",
"requires": { "requires": {
"color-convert": "^1.9.1", "whatwg-fetch": "2.0.4"
"color-string": "^1.5.2"
}
},
"color-string": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
"integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
} }
}, },
"lodash": { "lodash": {
"version": "4.17.4", "version": "4.17.13",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.13.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" "integrity": "sha512-vm3/XWXfWtRua0FkUyEHBZy8kCPjErNBT9fJx8Zvs+U6zjqPbTUOpkaoum3O5uiA8sm+yNMHXfYkTUHFoMxFNA=="
},
"whatwg-fetch": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
"integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
} }
} }
}, },
"@pnp/spfx-property-controls": { "@pnp/spfx-property-controls": {
"version": "1.14.1", "version": "1.20.0",
"resolved": "https://registry.npmjs.org/@pnp/spfx-property-controls/-/spfx-property-controls-1.14.1.tgz", "resolved": "https://registry.npmjs.org/@pnp/spfx-property-controls/-/spfx-property-controls-1.20.0.tgz",
"integrity": "sha512-GN3mmqpBJtOJJX/tCYXU1SZPCm25HGFfLkhRo+C3PEZ7NzmpbLqaIjrMD2ePG4C+UEkKOubmh1sn/9LiYNtOSg==", "integrity": "sha512-+V7IUNHABJd62lXZzyDbqBqZVeeHBPuy1L+X98aIa2pagCvSuDNQOz6MHvP6iGExTK+MrSB0XgZZk1u4kfz6BQ==",
"requires": { "requires": {
"@pnp/common": "^1.2.8", "@pnp/common": "^1.2.8",
"@pnp/logging": "^1.2.8", "@pnp/logging": "^1.2.8",
@ -4209,15 +4205,17 @@
"@pnp/sp": "^1.2.8", "@pnp/sp": "^1.2.8",
"@pnp/sp-clientsvc": "^1.2.8", "@pnp/sp-clientsvc": "^1.2.8",
"@pnp/sp-taxonomy": "^1.2.8", "@pnp/sp-taxonomy": "^1.2.8",
"@pnp/telemetry-js": "1.0.0", "@pnp/telemetry-js": "2.0.0",
"lodash.omit": "^4.5.0",
"markdown-to-jsx": "^6.11.4",
"office-ui-fabric-react": "5.131.0", "office-ui-fabric-react": "5.131.0",
"react-ace": "5.8.0" "react-ace": "5.8.0"
} }
}, },
"@pnp/telemetry-js": { "@pnp/telemetry-js": {
"version": "1.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/@pnp/telemetry-js/-/telemetry-js-1.0.0.tgz", "resolved": "https://registry.npmjs.org/@pnp/telemetry-js/-/telemetry-js-2.0.0.tgz",
"integrity": "sha512-7Lr22EB6DgB8MZi0WDuou8VuXru3wHdiOQPenB2B2gdhp7bJj2ijN9vTiqF8aL1nh80uJxIyX269Ix/PSnJC7g==", "integrity": "sha512-qFNm3mTerTnxgTR6c/4iMMt8EUKrQn5z0XG/IQtpNlp6m7KXRDFR87mQKeBVtSv2LhxGO0VNFndKJIibBw52zQ==",
"requires": { "requires": {
"whatwg-fetch": "2.0.4" "whatwg-fetch": "2.0.4"
}, },
@ -4525,6 +4523,14 @@
"integrity": "sha1-aQoUdbhPKohP0HzXl8APXzE1bqg=", "integrity": "sha1-aQoUdbhPKohP0HzXl8APXzE1bqg=",
"dev": true "dev": true
}, },
"@types/quill": {
"version": "1.3.10",
"resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz",
"integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==",
"requires": {
"parchment": "^1.1.2"
}
},
"@types/ramda": { "@types/ramda": {
"version": "0.25.51", "version": "0.25.51",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/@types/ramda/-/ramda-0.25.51.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/@types/ramda/-/ramda-0.25.51.tgz",
@ -6791,6 +6797,15 @@
"unset-value": "^1.0.0" "unset-value": "^1.0.0"
} }
}, },
"call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
}
},
"caller-callsite": { "caller-callsite": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/caller-callsite/-/caller-callsite-2.0.0.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/caller-callsite/-/caller-callsite-2.0.0.tgz",
@ -6926,25 +6941,18 @@
} }
}, },
"chartjs-color": { "chartjs-color": {
"version": "2.2.0", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.2.0.tgz", "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz",
"integrity": "sha1-hKL7dVeH7YXDndbdjHsdiEKbrq4=", "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==",
"requires": { "requires": {
"chartjs-color-string": "^0.5.0", "chartjs-color-string": "^0.6.0",
"color-convert": "^0.5.3" "color-convert": "^1.9.3"
},
"dependencies": {
"color-convert": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
"integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0="
}
} }
}, },
"chartjs-color-string": { "chartjs-color-string": {
"version": "0.5.0", "version": "0.6.0",
"resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz", "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz",
"integrity": "sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==", "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==",
"requires": { "requires": {
"color-name": "^1.0.0" "color-name": "^1.0.0"
} }
@ -7247,7 +7255,6 @@
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/color/-/color-3.1.2.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/color/-/color-3.1.2.tgz",
"integrity": "sha1-aBSOf4XUGtdknF+oyBBvCY0inhA=", "integrity": "sha1-aBSOf4XUGtdknF+oyBBvCY0inhA=",
"dev": true,
"requires": { "requires": {
"color-convert": "^1.9.1", "color-convert": "^1.9.1",
"color-string": "^1.5.2" "color-string": "^1.5.2"
@ -7270,7 +7277,6 @@
"version": "1.5.3", "version": "1.5.3",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/color-string/-/color-string-1.5.3.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/color-string/-/color-string-1.5.3.tgz",
"integrity": "sha1-ybvF8BtYtUkvPWhXRZy2WQziBMw=", "integrity": "sha1-ybvF8BtYtUkvPWhXRZy2WQziBMw=",
"dev": true,
"requires": { "requires": {
"color-name": "^1.0.0", "color-name": "^1.0.0",
"simple-swizzle": "^0.2.2" "simple-swizzle": "^0.2.2"
@ -7558,6 +7564,15 @@
"sha.js": "^2.4.8" "sha.js": "^2.4.8"
} }
}, },
"create-react-class": {
"version": "15.7.0",
"resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.7.0.tgz",
"integrity": "sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==",
"requires": {
"loose-envify": "^1.3.1",
"object-assign": "^4.1.1"
}
},
"cross-spawn": { "cross-spawn": {
"version": "6.0.5", "version": "6.0.5",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/cross-spawn/-/cross-spawn-6.0.5.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/cross-spawn/-/cross-spawn-6.0.5.tgz",
@ -8104,6 +8119,19 @@
"esprima": "4.0.1" "esprima": "4.0.1"
} }
}, },
"deep-equal": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
"integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
"requires": {
"is-arguments": "^1.0.4",
"is-date-object": "^1.0.1",
"is-regex": "^1.0.4",
"object-is": "^1.0.1",
"object-keys": "^1.1.1",
"regexp.prototype.flags": "^1.2.0"
}
},
"deep-is": { "deep-is": {
"version": "0.1.3", "version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@ -8166,7 +8194,6 @@
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/define-properties/-/define-properties-1.1.3.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=",
"dev": true,
"requires": { "requires": {
"object-keys": "^1.0.12" "object-keys": "^1.0.12"
} }
@ -9214,6 +9241,11 @@
"through": "^2.3.8" "through": "^2.3.8"
} }
}, },
"eventemitter3": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
"integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo="
},
"events": { "events": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/events/-/events-3.1.0.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/events/-/events-3.1.0.tgz",
@ -9453,8 +9485,7 @@
"extend": { "extend": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
"dev": true
}, },
"extend-shallow": { "extend-shallow": {
"version": "3.0.2", "version": "3.0.2",
@ -9577,6 +9608,11 @@
"integrity": "sha1-VFFFB3xQFJHjOxXsQIwpQ3bpSuQ=", "integrity": "sha1-VFFFB3xQFJHjOxXsQIwpQ3bpSuQ=",
"dev": true "dev": true
}, },
"fast-diff": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig=="
},
"fast-json-stable-stringify": { "fast-json-stable-stringify": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@ -10111,7 +10147,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -10132,12 +10169,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -10152,17 +10191,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -10279,7 +10321,8 @@
"inherits": { "inherits": {
"version": "2.0.4", "version": "2.0.4",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -10291,6 +10334,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -10305,6 +10349,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -10312,12 +10357,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.9.0", "version": "2.9.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -10336,6 +10383,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -10425,7 +10473,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -10437,6 +10486,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -10522,7 +10572,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -10558,6 +10609,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -10577,6 +10629,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -10620,12 +10673,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.1.1", "version": "3.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },
@ -10644,8 +10699,7 @@
"function-bind": { "function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0="
"dev": true
}, },
"functional-red-black-tree": { "functional-red-black-tree": {
"version": "1.0.1", "version": "1.0.1",
@ -10713,6 +10767,16 @@
"integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=", "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=",
"dev": true "dev": true
}, },
"get-intrinsic": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1"
}
},
"get-stdin": { "get-stdin": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
@ -11331,7 +11395,6 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/has/-/has-1.0.3.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/has/-/has-1.0.3.tgz",
"integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=",
"dev": true,
"requires": { "requires": {
"function-bind": "^1.1.1" "function-bind": "^1.1.1"
} }
@ -11363,8 +11426,7 @@
"has-symbols": { "has-symbols": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/has-symbols/-/has-symbols-1.0.1.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/has-symbols/-/has-symbols-1.0.1.tgz",
"integrity": "sha1-n1IUdYpEGWxAbZvXbOv4HsLdMeg=", "integrity": "sha1-n1IUdYpEGWxAbZvXbOv4HsLdMeg="
"dev": true
}, },
"has-unicode": { "has-unicode": {
"version": "2.0.1", "version": "2.0.1",
@ -12004,6 +12066,14 @@
} }
} }
}, },
"is-arguments": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz",
"integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==",
"requires": {
"call-bind": "^1.0.0"
}
},
"is-arrayish": { "is-arrayish": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@ -12077,8 +12147,7 @@
"is-date-object": { "is-date-object": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/is-date-object/-/is-date-object-1.0.2.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/is-date-object/-/is-date-object-1.0.2.tgz",
"integrity": "sha1-vac28s2P0G0yhE53Q7+nSUw7/X4=", "integrity": "sha1-vac28s2P0G0yhE53Q7+nSUw7/X4="
"dev": true
}, },
"is-descriptor": { "is-descriptor": {
"version": "0.1.6", "version": "0.1.6",
@ -12252,7 +12321,6 @@
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/is-regex/-/is-regex-1.0.5.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/is-regex/-/is-regex-1.0.5.tgz",
"integrity": "sha1-OdWJo1i/GJZ/cmlnEguPwa7XTq4=", "integrity": "sha1-OdWJo1i/GJZ/cmlnEguPwa7XTq4=",
"dev": true,
"requires": { "requires": {
"has": "^1.0.3" "has": "^1.0.3"
} }
@ -14833,6 +14901,11 @@
"integrity": "sha1-VYqlO0O2YeGSWgr9+japoQhf5Xo=", "integrity": "sha1-VYqlO0O2YeGSWgr9+japoQhf5Xo=",
"dev": true "dev": true
}, },
"lodash.omit": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz",
"integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA="
},
"lodash.restparam": { "lodash.restparam": {
"version": "3.6.1", "version": "3.6.1",
"resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz",
@ -15015,6 +15088,15 @@
"object-visit": "^1.0.0" "object-visit": "^1.0.0"
} }
}, },
"markdown-to-jsx": {
"version": "6.11.4",
"resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-6.11.4.tgz",
"integrity": "sha512-3lRCD5Sh+tfA52iGgfs/XZiw33f7fFX9Bn55aNnVNUd2GzLDkOWyKYYD8Yju2B1Vn+feiEdgJs8T6Tg0xNokPw==",
"requires": {
"prop-types": "^15.6.2",
"unquote": "^1.1.0"
}
},
"matchdep": { "matchdep": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/matchdep/-/matchdep-2.0.0.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/matchdep/-/matchdep-2.0.0.tgz",
@ -15381,9 +15463,9 @@
} }
}, },
"moment": { "moment": {
"version": "2.24.0", "version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
}, },
"move-concurrently": { "move-concurrently": {
"version": "1.0.1", "version": "1.0.1",
@ -15950,11 +16032,19 @@
"integrity": "sha1-9Pa9GBrXfwBrXs5gvQtvOY/3Smc=", "integrity": "sha1-9Pa9GBrXfwBrXs5gvQtvOY/3Smc=",
"dev": true "dev": true
}, },
"object-is": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
"integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
}
},
"object-keys": { "object-keys": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/object-keys/-/object-keys-1.1.1.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=", "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4="
"dev": true
}, },
"object-visit": { "object-visit": {
"version": "1.0.1", "version": "1.0.1",
@ -16369,6 +16459,11 @@
"no-case": "^2.2.0" "no-case": "^2.2.0"
} }
}, },
"parchment": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg=="
},
"parent-module": { "parent-module": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/parent-module/-/parent-module-1.0.1.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/parent-module/-/parent-module-1.0.1.tgz",
@ -17595,6 +17690,36 @@
"integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
"dev": true "dev": true
}, },
"quill": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
"requires": {
"clone": "^2.1.1",
"deep-equal": "^1.0.1",
"eventemitter3": "^2.0.3",
"extend": "^3.0.2",
"parchment": "^1.1.4",
"quill-delta": "^3.6.2"
},
"dependencies": {
"clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
}
}
},
"quill-delta": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
"requires": {
"deep-equal": "^1.0.1",
"extend": "^3.0.2",
"fast-diff": "1.1.2"
}
},
"raf": { "raf": {
"version": "3.4.1", "version": "3.4.1",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
@ -17755,6 +17880,11 @@
"prop-types": "^15.6.0" "prop-types": "^15.6.0"
} }
}, },
"react-dom-factories": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/react-dom-factories/-/react-dom-factories-1.0.2.tgz",
"integrity": "sha1-63cFxNs2+1AbOqOP91lhaqD/luA="
},
"react-is": { "react-is": {
"version": "16.8.2", "version": "16.8.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.2.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.2.tgz",
@ -17765,6 +17895,27 @@
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
}, },
"react-quill": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/react-quill/-/react-quill-1.3.3.tgz",
"integrity": "sha512-T9RubLaWJ8gCfp7sOqmFupjiTiEp/EdGqhCG+PWGKc5UHiK6xIWNKWYsOHHEhQ+sZCKs8u/DPx47gc1VfFmcLg==",
"requires": {
"@types/quill": "1.3.10",
"@types/react": "*",
"create-react-class": "^15.6.0",
"lodash": "^4.17.4",
"prop-types": "^15.5.10",
"quill": "^1.2.6",
"react-dom-factories": "^1.0.0"
},
"dependencies": {
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
}
}
},
"react-sortable-tree": { "react-sortable-tree": {
"version": "2.6.0", "version": "2.6.0",
"resolved": "https://registry.npmjs.org/react-sortable-tree/-/react-sortable-tree-2.6.0.tgz", "resolved": "https://registry.npmjs.org/react-sortable-tree/-/react-sortable-tree-2.6.0.tgz",
@ -18022,6 +18173,15 @@
"safe-regex": "^1.1.0" "safe-regex": "^1.1.0"
} }
}, },
"regexp.prototype.flags": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz",
"integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==",
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
}
},
"regexpp": { "regexpp": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/regexpp/-/regexpp-2.0.1.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/regexpp/-/regexpp-2.0.1.tgz",
@ -20479,8 +20639,7 @@
"unquote": { "unquote": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/unquote/-/unquote-1.1.1.tgz", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/unquote/-/unquote-1.1.1.tgz",
"integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ="
"dev": true
}, },
"unset-value": { "unset-value": {
"version": "1.0.0", "version": "1.0.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "react-tree-orgchart", "name": "react-tree-orgchart",
"version": "1.0.2", "version": "1.1.0",
"private": true, "private": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
@ -15,13 +15,13 @@
"@microsoft/sp-lodash-subset": "1.10.0", "@microsoft/sp-lodash-subset": "1.10.0",
"@microsoft/sp-office-ui-fabric-core": "1.10.0", "@microsoft/sp-office-ui-fabric-core": "1.10.0",
"@microsoft/sp-webpart-base": "1.10.0", "@microsoft/sp-webpart-base": "1.10.0",
"@pnp/common": "^1.2.9", "@pnp/common": "1.3.11",
"@pnp/graph": "^1.2.9", "@pnp/graph": "1.3.11",
"@pnp/logging": "^1.2.9", "@pnp/logging": "1.3.11",
"@pnp/odata": "^1.2.9", "@pnp/odata": "1.3.11",
"@pnp/sp": "^1.2.9", "@pnp/sp": "1.3.11",
"@pnp/spfx-controls-react": "^1.11.0", "@pnp/spfx-controls-react": "1.21.1",
"@pnp/spfx-property-controls": "^1.14.1", "@pnp/spfx-property-controls": "1.20.0",
"@types/es6-promise": "0.0.33", "@types/es6-promise": "0.0.33",
"@types/react": "16.4.2", "@types/react": "16.4.2",
"@types/react-dom": "16.0.5", "@types/react-dom": "16.0.5",

View File

@ -0,0 +1,58 @@
import { WebPartContext } from "@microsoft/sp-webpart-base";
import { graph } from "@pnp/graph";
export interface IGraphUser {
mail?: string;
displayName?: string;
jobTitle?: string;
userPrincipalName?: string;
}
const graphUserSelect: string[] = ['displayName', 'mail', 'jobTitle', 'userPrincipalName'];
export default class GraphService {
constructor(private context: WebPartContext) {
graph.setup({
spfxContext: this.context
});
}
public async getUser(upn: string): Promise<IGraphUser> {
return await graph.users.getById(upn).select(...graphUserSelect).get() as IGraphUser;
}
public async getUserManger(upn: string): Promise<IGraphUser> {
return await graph.users.getById(upn).manager.select(...graphUserSelect).get() as IGraphUser;
}
public async getUserDirectReports(upn: string, excludefilter?: boolean, filter?: string) {
/*
odata filter
"code": "Request_UnsupportedQuery",
"message": "The specified filter to the reference property query is currently not supported.",
*/
const directReports = await graph.users.getById(upn).directReports.select(...graphUserSelect).get() as IGraphUser[];
if (filter && filter.length > 0) {
if (excludefilter) {
return directReports.filter((user) =>
user.userPrincipalName?.toLowerCase().indexOf(filter.toLowerCase()) === -1
);
} else {
return directReports.filter((user) =>
user.userPrincipalName?.toLowerCase().indexOf(filter.toLowerCase()) !== -1
);
}
}
return directReports;
}
}

View File

@ -12,7 +12,7 @@
// Components that allow authors to embed arbitrary script code should set this to true. // 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 // https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
"requiresCustomScript": false, "requiresCustomScript": false,
//"viewType": 1,
"preconfiguredEntries": [{ "preconfiguredEntries": [{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other "groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
"group": { "default": "Other" }, "group": { "default": "Other" },
@ -22,6 +22,7 @@
"properties": { "properties": {
"title": "My Team Organization Chart", "title": "My Team Organization Chart",
"currentUserTeam": true, "currentUserTeam": true,
"maxLevels": 5 "maxLevels": 5
} }
}] }]

View File

@ -1,36 +1,48 @@
import * as React from 'react'; import * as React from 'react';
import * as ReactDom from 'react-dom'; import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library'; import { Version } from '@microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneTextField,
PropertyPaneToggle
} from '@microsoft/sp-webpart-base';
import * as strings from 'TreeOrgChartWebPartStrings'; import * as strings from 'TreeOrgChartWebPartStrings';
import TreeOrgChart from './components/TreeOrgChart'; import TreeOrgChart, { TreeOrgChartType } from './components/TreeOrgChart';
import { ITreeOrgChartProps } from './components/ITreeOrgChartProps'; import { ITreeOrgChartProps } from './components/ITreeOrgChartProps';
import { PropertyFieldNumber } from '@pnp/spfx-property-controls/lib/PropertyFieldNumber'; import { PropertyFieldNumber } from '@pnp/spfx-property-controls/lib/PropertyFieldNumber';
import { setup as pnpSetup } from '@pnp/common'; import { setup as pnpSetup } from '@pnp/common';
import { BaseClientSideWebPart, IPropertyPaneConfiguration, PropertyPaneDropdown, PropertyPaneTextField, PropertyPaneToggle } from '@microsoft/sp-webpart-base';
import { graph } from "@pnp/graph";
export interface ITreeOrgChartWebPartProps { export interface ITreeOrgChartWebPartProps {
title: string; title: string;
currentUserTeam: boolean; currentUserTeam: boolean;
teamLeader: string;
maxLevels: number; maxLevels: number;
viewType: TreeOrgChartType;
filter: string;
excludefilter: boolean;
detailBehavoir: boolean;
} }
export default class TreeOrgChartWebPart extends BaseClientSideWebPart<ITreeOrgChartWebPartProps> { export default class TreeOrgChartWebPart extends BaseClientSideWebPart<ITreeOrgChartWebPartProps> {
public onInit(): Promise<void> { public onInit(): Promise<void> {
pnpSetup({ pnpSetup({
spfxContext: this.context spfxContext: this.context
}); });
graph.setup(this.context as any);
//Migration old Config Settings
if (!this.properties.viewType) {
const treetype = this.properties.currentUserTeam ? TreeOrgChartType.MyTeam : TreeOrgChartType.CompanyHierarchy;
this.properties.viewType = treetype;
}
return Promise.resolve(); return Promise.resolve();
} }
public render(): void { public render(): void {
const element: React.ReactElement<ITreeOrgChartProps> = React.createElement( const element: React.ReactElement<ITreeOrgChartProps> = React.createElement(
TreeOrgChart, TreeOrgChart,
{ {
@ -39,8 +51,16 @@ export default class TreeOrgChartWebPart extends BaseClientSideWebPart<ITreeOrgC
updateProperty: (value: string) => { updateProperty: (value: string) => {
this.properties.title = value; this.properties.title = value;
}, },
currentUserTeam: this.properties.currentUserTeam, viewType: this.properties.viewType,
teamLeader: this.properties.teamLeader,
updateTeamLeader: (loginname: string) => {
this.properties.teamLeader = loginname;
this.render();
},
maxLevels: this.properties.maxLevels, maxLevels: this.properties.maxLevels,
filter: this.properties.filter,
excludefilter: this.properties.excludefilter,
detailBehavoir: this.properties.detailBehavoir,
context: this.context context: this.context
} }
); );
@ -70,9 +90,16 @@ export default class TreeOrgChartWebPart extends BaseClientSideWebPart<ITreeOrgC
PropertyPaneTextField('title', { PropertyPaneTextField('title', {
label: strings.TitleFieldLabel label: strings.TitleFieldLabel
}), }),
PropertyPaneToggle('currentUserTeam', { PropertyPaneDropdown('viewType', {
label: strings.CurrentUserTeamFieldLabel label: strings.ViewType,
options: [
{ key: TreeOrgChartType.MyTeam, text: strings.TreeOrgChartTypeMyTeam },
{ key: TreeOrgChartType.CompanyHierarchy, text: strings.TreeOrgChartTypeCompany },
{ key: TreeOrgChartType.ShowOtherTeam, text: strings.TreeOrgChartTypeShowOtherTeam },
],
selectedKey: this.properties.viewType
}), }),
PropertyFieldNumber("maxLevels", { PropertyFieldNumber("maxLevels", {
key: "numberValue", key: "numberValue",
label: strings.MaxLevels, label: strings.MaxLevels,
@ -81,9 +108,29 @@ export default class TreeOrgChartWebPart extends BaseClientSideWebPart<ITreeOrgC
maxValue: 10, maxValue: 10,
minValue: 1, minValue: 1,
disabled: false disabled: false
}) }),
PropertyPaneToggle('detailBehavoir', {
label: strings.DetailBehavoir,
onText: strings.LivePersonaCard,
offText: strings.DelveLink
}),
]
},
{
groupName: strings.FilterGroupName,
groupFields: [
PropertyPaneToggle('excludefilter', {
label: strings.ExcludeFilter,
onText: strings.ExcludeFilterOnText,
offText: strings.ExcludeFilterOffText
}),
PropertyPaneTextField('filter', {
label: strings.FilterLabel,
description: strings.FilterDescription,
}),
] ]
} }
] ]
} }
] ]

View File

@ -1,5 +0,0 @@
export interface ITreeChildren {
title ? : any;
expanded ? :boolean;
children ? : any;
}

View File

@ -1,6 +1,6 @@
import {ITreeChildren } from './ITreeChildren';
export interface ITreeData { export interface ITreeData {
title: any; title: any;
expanded ?: boolean; expanded ?: boolean;
children ? : ITreeChildren[]; children ? : ITreeData[]|null;
} }

View File

@ -1,10 +1,16 @@
import { DisplayMode } from '@microsoft/sp-core-library'; import { DisplayMode } from '@microsoft/sp-core-library';
import { WebPartContext } from "@microsoft/sp-webpart-base"; import { WebPartContext } from "@microsoft/sp-webpart-base";
import { TreeOrgChartType } from './TreeOrgChart';
export interface ITreeOrgChartProps { export interface ITreeOrgChartProps {
title: string; title: string;
currentUserTeam:boolean;
maxLevels: number; maxLevels: number;
displayMode: DisplayMode; displayMode: DisplayMode;
updateProperty: (value: string) => void; updateProperty: (value: string) => void;
viewType: TreeOrgChartType;
teamLeader?: string;
updateTeamLeader: (loginname: string) => void;
context: WebPartContext; context: WebPartContext;
filter: string;
excludefilter: boolean;
detailBehavoir: boolean;
} }

View File

@ -1,4 +1,5 @@
export interface ITreeOrgChartState { export interface ITreeOrgChartState {
treeData: any; treeData: any;
isLoading: boolean; isLoading: boolean;
livePersonaCard?: any;
} }

View File

@ -16,12 +16,25 @@ import {
import { IconButton } from "office-ui-fabric-react/lib/Button"; import { IconButton } from "office-ui-fabric-react/lib/Button";
import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle"; import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle";
import SPService from "../../../services/SPServices"; import SPService from "../../../services/SPServices";
import { ITreeChildren } from "./ITreeChildren";
import { ITreeData } from "./ITreeData"; import { ITreeData } from "./ITreeData";
import { import {
Spinner, Spinner,
SpinnerSize SpinnerSize
} from "office-ui-fabric-react/lib/components/Spinner"; } from "office-ui-fabric-react/lib/components/Spinner";
import { DisplayMode, Environment, EnvironmentType } from "@microsoft/sp-core-library";
import { PeoplePicker, PrincipalType } from "@pnp/spfx-controls-react/lib/PeoplePicker";
import { SPComponentLoader } from '@microsoft/sp-loader';
import * as strings from 'TreeOrgChartWebPartStrings';
import GraphServices, { IGraphUser } from "../../../services/GraphService";
import GraphService from "../../../services/GraphService";
export enum TreeOrgChartType {
MyTeam = 1,
CompanyHierarchy = 2,
ShowOtherTeam = 4
}
const LIVE_PERSONA_COMPONENT_ID: string = '914330ee-2df2-4f6e-a858-30c23a812408';
export default class TreeOrgChart extends React.Component< export default class TreeOrgChart extends React.Component<
ITreeOrgChartProps, ITreeOrgChartProps,
@ -29,11 +42,13 @@ export default class TreeOrgChart extends React.Component<
> { > {
private treeData: ITreeData[]; private treeData: ITreeData[];
private SPService: SPService; private SPService: SPService;
private GraphService: GraphService;
constructor(props) { constructor(props) {
super(props); super(props);
this.SPService = new SPService(this.props.context); this.SPService = new SPService(this.props.context);
this.GraphService = new GraphServices(this.props.context);
this.state = { this.state = {
treeData: [], treeData: [],
isLoading: true isLoading: true
@ -49,43 +64,97 @@ export default class TreeOrgChart extends React.Component<
prevState: ITreeOrgChartState prevState: ITreeOrgChartState
) { ) {
if ( if (
this.props.currentUserTeam !== prevProps.currentUserTeam || this.props.viewType !== prevProps.viewType ||
this.props.maxLevels !== prevProps.maxLevels this.props.maxLevels !== prevProps.maxLevels ||
this.props.teamLeader !== prevProps.teamLeader ||
this.props.excludefilter !== prevProps.excludefilter ||
this.props.filter !== prevProps.filter ||
this.props.detailBehavoir !== prevProps.detailBehavoir
) { ) {
await this.loadOrgchart(); await this.loadOrgchart();
} }
} }
public async componentDidMount() { public async componentDidMount() {
if (Environment.type !== EnvironmentType.Local) {
const sharedLibrary = await this._loadSPComponentById(
LIVE_PERSONA_COMPONENT_ID
);
const livePersonaCard: any = sharedLibrary.LivePersonaCard;
this.setState({ livePersonaCard: livePersonaCard });
}
await this.loadOrgchart(); await this.loadOrgchart();
} }
private async _loadSPComponentById(componentId: string): Promise<any> {
try {
const component: any = await SPComponentLoader.loadComponentById(
componentId
);
return component;
} catch (error) {
Promise.reject(error);
}
}
private livePersonaCard(user: IGraphUser): JSX.Element {
return React.createElement(
this.state.livePersonaCard,
{
serviceScope: this.props.context.serviceScope,
upn: user.userPrincipalName,
onCardOpen: () => {
console.log('LivePersonaCard Open');
},
onCardClose: () => {
console.log('LivePersonaCard Close');
},
}, this.buildDefaultPersonaCard(user)
);
}
/* /*
// Load Organization Chart // Load Organization Chart
*/ */
public async loadOrgchart() { public async loadOrgchart() {
this.setState({ treeData: [], isLoading: true }); this.setState({ treeData: [], isLoading: true });
const currentUser = `i:0#.f|membership|${this.props.context.pageContext.user.loginName}`; const currentUser = this.props.context.pageContext.user.loginName;
const currentUserProperties = await this.SPService.getUserProperties( let currentUserProperties = null;
currentUser
);
this.treeData = []; this.treeData = [];
// Test if show only my Team or All Organization Chart // Test if show only my Team or All Organization Chart
if (!this.props.currentUserTeam) { switch (this.props.viewType) {
case TreeOrgChartType.CompanyHierarchy:
const spcurrentlogin = `i:0#.f|membership|${currentUser}`;
currentUserProperties = await this.SPService.getUserProperties(
spcurrentlogin
);
const treeManagers = await this.buildOrganizationChart( const treeManagers = await this.buildOrganizationChart(
currentUserProperties currentUserProperties
); );
if (treeManagers) this.treeData.push(treeManagers); if (treeManagers) this.treeData.push(treeManagers);
} else { break;
const treeManagers = await this.buildMyTeamOrganizationChart( case TreeOrgChartType.MyTeam:
currentUserProperties const myteam = await this.buildMyTeamOrganizationChart(
currentUser
); );
if (treeManagers) if (myteam)
this.treeData.push({ this.treeData = [{ ...myteam }];
title: treeManagers.person, break;
expanded: true, case TreeOrgChartType.ShowOtherTeam:
children: treeManagers.treeChildren if (this.props.teamLeader && this.props.teamLeader.length > 0) {
});
const otherteam = await this.buildTeamLeaderOrganizationChart(
this.props.teamLeader
);
if (otherteam)
this.treeData = [{ ...otherteam }];
} }
break;
}
this.setState({ treeData: this.treeData, isLoading: false }); this.setState({ treeData: this.treeData, isLoading: false });
} }
@ -100,185 +169,131 @@ export default class TreeOrgChart extends React.Component<
currentUserProperties.ExtendedManagers && currentUserProperties.ExtendedManagers &&
currentUserProperties.ExtendedManagers.length > 0 currentUserProperties.ExtendedManagers.length > 0
) { ) {
const upn: string | undefined = this.claimUserToUPN(currentUserProperties.ExtendedManagers[0]);
if (upn) {
treeManagers = await this.getUsers( treeManagers = await this.getUsers(
currentUserProperties.ExtendedManagers[0] upn
); );
} }
}
return treeManagers; return treeManagers;
} }
/*
// Get user from Top Manager private claimUserToUPN(claim: string): string | undefined {
*/ if (!claim) { return undefined; }
private async getUsers(manager: string) { const claimuser: string[] = claim.split('|');
let person: any; if (claimuser.length > 1) {
const upn = claimuser[claimuser.length - 1];
if (upn && upn.length > 0 && upn.indexOf('@') !== -1) {
return upn;
}
}
return undefined;
}
public buildPersonaCard(user: IGraphUser): JSX.Element {
if (this.props.detailBehavoir) {
if (this.state.livePersonaCard) {
return (this.livePersonaCard(user));
}
return this.buildDefaultPersonaCard(user);
} else {
return this.buildDefaultPersonaCard(user);
}
}
public buildDefaultPersonaCard(user: IGraphUser): JSX.Element {
let spUser: IPersonaSharedProps = {}; let spUser: IPersonaSharedProps = {};
// Get User Properties let imageInitials: string[] = user.displayName ? user.displayName.split(" ") : [];
const managerProperties = await this.SPService.getUserProperties(manager); //https://graph.microsoft.com/v1.0/users/${upn}/photo/$value
let imageInitials: string[] = managerProperties.DisplayName.split(" ");
// Persona Card Properties // Persona Card Properties
spUser.imageUrl = `/_layouts/15/userphoto.aspx?size=L&username=${managerProperties.Email}`; spUser.imageUrl = user.userPrincipalName ? `/_layouts/15/userphoto.aspx?size=L&username=${user.userPrincipalName}` : undefined;
spUser.imageInitials = imageInitials && imageInitials.length > 0 ? `${imageInitials[0] spUser.imageInitials = imageInitials && imageInitials.length > 0 ? `${imageInitials[0]
.substring(0, 1) .substring(0, 1)
.toUpperCase()}${imageInitials[1] ? imageInitials[1].substring(0, 1).toUpperCase() : ''}` : ''; .toUpperCase()}${imageInitials[1] ? imageInitials[1].substring(0, 1).toUpperCase() : ''}` : '';
spUser.text = managerProperties.DisplayName; spUser.text = user.displayName;
spUser.tertiaryText = managerProperties.Email; spUser.tertiaryText = user.mail;
spUser.secondaryText = managerProperties.Title; spUser.secondaryText = user.jobTitle;
// PersonaCard component // PersonaCard component
person = ( return (
<Persona <Persona
{...spUser} {...spUser}
hidePersonaDetails={false} hidePersonaDetails={false}
size={PersonaSize.size40} size={PersonaSize.size40}
/> />
); );
// Has DirectReports }
if (
managerProperties.DirectReports &&
managerProperties.DirectReports.length > 0 private async getUsers(upn: string): Promise<ITreeData | null> {
) { const managerUser = await this.GraphService.getUser(upn);
const usersDirectReports: any[] = await this.getChildren( const person = this.buildPersonaCard(managerUser);
managerProperties.DirectReports if (managerUser.userPrincipalName) {
); return ({
// return treeData title: person,
return { title: person, expanded: true, children: usersDirectReports }; expanded: true,
// Don't have DirectReports children: await this.getDirectReportsUsers(managerUser.userPrincipalName)
});
} else { } else {
// return treeData
return { title: person }; return { title: person };
} }
} }
// Get Children (user DirectReports)
private async getChildren(userDirectReports: any[]) {
let treeChildren: ITreeChildren[] = [];
let spUser: IPersonaSharedProps = {};
for (const user of userDirectReports) { private async getDirectReportsUsers(upn?: string, level: number = 1, expanded: boolean = false): Promise<ITreeData[] | null> {
const managerProperties = await this.SPService.getUserProperties(user); if (!upn) { return null; }
const imageInitials: string[] = managerProperties.DisplayName.split(" ");
spUser.imageUrl = `/_layouts/15/userphoto.aspx?size=L&username=${managerProperties.Email}`;
spUser.imageInitials = imageInitials && imageInitials.length > 0 ? `${imageInitials[0]
.substring(0, 1)
.toUpperCase()}${imageInitials[1] ? imageInitials[1].substring(0, 1).toUpperCase(): ''}` : '';
spUser.text = managerProperties.DisplayName;
spUser.tertiaryText = managerProperties.Email;
spUser.secondaryText = managerProperties.Title;
const person = (
<Persona
{...spUser}
hidePersonaDetails={false}
size={PersonaSize.size40}
/>
);
const usersDirectReports = await this.getChildren(
managerProperties.DirectReports
);
usersDirectReports const directReportsUser = await this.GraphService.getUserDirectReports(upn,this.props.excludefilter,this.props.filter);
? treeChildren.push({ title: person, children: usersDirectReports }) //this is already level 1
: treeChildren.push({ title: person }); if (directReportsUser && directReportsUser.length > 0) {
return await Promise.all(directReportsUser.map(async (dr) => {
const children = ((level +1) <= this.props.maxLevels) ? await this.getDirectReportsUsers(dr.userPrincipalName, level + 1) : null;
return ({
title: this.buildPersonaCard(dr),
expanded: expanded,
children: children
});
}));
} }
return treeChildren; return null;
} }
//buildTeamLeaderOrganizationChart
private async buildTeamLeaderOrganizationChart(upn: string): Promise<ITreeData | null> {
const tmpupn: string | undefined = this.claimUserToUPN(upn);
return await this.getUsers(tmpupn ? tmpupn : upn);
}
/* /*
Build My Team Organization Chart Build My Team Organization Chart
@parm: currentUserProperties @parm: currentUserProperties
*/ */
private async buildMyTeamOrganizationChart(currentUserProperties: any) { private async buildMyTeamOrganizationChart(upn: string): Promise<ITreeData | null> {
let manager: IPersonaSharedProps = {};
let me: IPersonaSharedProps = {};
let treeChildren: ITreeChildren[] = [];
let peer: IPersonaSharedProps = {};
let imageInitials: string[];
let hasManager: boolean = false;
let managerCard: any;
// Get My Manager
const myManager = await this.SPService.getUserProfileProperty(
currentUserProperties.AccountName,
"Manager"
);
// Get My Manager Properties
if (myManager) {
const managerProperties = await this.SPService.getUserProperties(
myManager
);
imageInitials = managerProperties.DisplayName?.split(" ").map(name => name[0]);
// PersonaCard Props
manager.imageUrl = `/_layouts/15/userphoto.aspx?size=L&username=${managerProperties.Email}`;
if (imageInitials)
manager.imageInitials = `${imageInitials[0]}${imageInitials[1] ? imageInitials[1]: ''}`.toUpperCase();
manager.text = managerProperties.DisplayName;
manager.tertiaryText = managerProperties.Email;
manager.secondaryText = managerProperties.Title;
// PersonaCard Component
managerCard = (
<Persona
{...manager}
hidePersonaDetails={false}
size={PersonaSize.size40}
/>
);
hasManager = true;
}
// Get my Properties const mymanager = await this.GraphService.getUserManger(upn);
const meImageInitials: string[] = currentUserProperties.DisplayName.split( if (mymanager && mymanager.userPrincipalName) {
" " return await this.getUsers(mymanager.userPrincipalName);
);
me.imageUrl = `/_layouts/15/userphoto.aspx?size=L&username=${currentUserProperties.Email}`;
me.imageInitials = me.imageInitials && me.imageInitials.length > 0 ?`${meImageInitials[0]
.substring(0, 1)
.toUpperCase()}${meImageInitials[1] ? meImageInitials[1].substring(0, 1).toUpperCase():''}` : '';
me.text = currentUserProperties.DisplayName;
me.tertiaryText = currentUserProperties.Email;
me.secondaryText = currentUserProperties.Title;
const meCard = (
<Persona {...me} hidePersonaDetails={false} size={PersonaSize.size40} />
);
const usersDirectReports: any[] = await this.getChildren(
currentUserProperties.DirectReports
);
// Current USer Has Manager
if (hasManager) {
treeChildren.push({
title: meCard,
expanded: true,
children: usersDirectReports
});
} else {
treeChildren = usersDirectReports;
managerCard = meCard;
} }
return await this.getUsers(upn);
// Get MyPeers
for (const userPeer of currentUserProperties.Peers) {
const peerProperties = await this.SPService.getUserProperties(userPeer);
imageInitials = peerProperties.DisplayName.split(" ");
peer.imageUrl = `/_layouts/15/userphoto.aspx?size=L&username=${peerProperties.Email}`;
peer.imageInitials = peer.imageInitials && peer.imageInitials.length>0 ? `${imageInitials[0]
.substring(0, 1)
.toUpperCase()}${imageInitials[1] ? imageInitials[1].substring(0, 1).toUpperCase():''}` : '';
peer.text = peerProperties.DisplayName;
peer.tertiaryText = peerProperties.Email;
peer.secondaryText = peerProperties.Title;
const peerCard = (
<Persona
{...peer}
hidePersonaDetails={false}
size={PersonaSize.size40}
/>
);
treeChildren.push({ title: peerCard });
}
// Return
return { person: managerCard, treeChildren: treeChildren };
} }
// Render // Render
public render(): React.ReactElement<ITreeOrgChartProps> { public render(): React.ReactElement<ITreeOrgChartProps> {
const showEditOther: boolean = this.props.displayMode === DisplayMode.Edit && this.props.viewType === TreeOrgChartType.ShowOtherTeam;
let selectedTeamleader: string | undefined = undefined;
if (showEditOther && this.props.teamLeader && this.props.teamLeader.length > 0) {
selectedTeamleader = this.claimUserToUPN(this.props.teamLeader);
if (!selectedTeamleader) {
selectedTeamleader == this.props.teamLeader;
}
}
return ( return (
<div className={styles.treeOrgChart}> <div className={styles.treeOrgChart}>
<WebPartTitle <WebPartTitle
@ -286,6 +301,32 @@ export default class TreeOrgChart extends React.Component<
title={this.props.title} title={this.props.title}
updateProperty={this.props.updateProperty} updateProperty={this.props.updateProperty}
/> />
{showEditOther && (<div>
<PeoplePicker
context={this.props.context}
titleText={strings.TeamLeaderHeadline}
personSelectionLimit={1}
groupName={""} // Leave this blank in case you want to filter from all users
isRequired={true}
disabled={false}
defaultSelectedUsers={selectedTeamleader ? [selectedTeamleader] : undefined}
selectedItems={(items: any) => {
if (this.props.updateTeamLeader) {
if (items.length > 0) {
const teamleaderupn: string | undefined = this.claimUserToUPN(items[0].loginName);
if (teamleaderupn) {
this.props.updateTeamLeader(teamleaderupn);
return;
}
}
this.props.updateTeamLeader('');
}
}}
showHiddenInUI={false}
principalTypes={[PrincipalType.User]}
resolveDelay={1000} />
</div>)}
{this.state.isLoading ? ( {this.state.isLoading ? (
<Spinner <Spinner
size={SpinnerSize.large} size={SpinnerSize.large}
@ -297,17 +338,18 @@ export default class TreeOrgChart extends React.Component<
treeData={this.state.treeData} treeData={this.state.treeData}
onChange={this.handleTreeOnChange.bind(this)} onChange={this.handleTreeOnChange.bind(this)}
canDrag={false} canDrag={false}
canDrop={false}
rowHeight={70} rowHeight={70}
maxDepth={this.props.maxLevels} maxDepth={this.props.maxLevels}
generateNodeProps={rowInfo => ({ generateNodeProps={rowInfo => {
return !this.props.detailBehavoir ?
({
buttons: [ buttons: [
<IconButton <IconButton
disabled={false} disabled={false}
checked={false} checked={false}
iconProps={{ iconName: "ContactInfo" }} iconProps={{ iconName: "ContactInfo" }}
title="Contact Info" title={strings.ContactInfoTitle}
ariaLabel="Contact" ariaLabel={strings.ContactInfoTitle}
onClick={() => { onClick={() => {
window.open( window.open(
`https://eur.delve.office.com/?p=${rowInfo.node.title.props.tertiaryText}&v=work` `https://eur.delve.office.com/?p=${rowInfo.node.title.props.tertiaryText}&v=work`
@ -315,7 +357,9 @@ export default class TreeOrgChart extends React.Component<
}} }}
/> />
] ]
})} }) : undefined;
}
}
/> />
</div> </div>
</div> </div>

View File

@ -3,7 +3,21 @@ define([], function () {
"PropertyPaneDescription": "Tree Organization Chart", "PropertyPaneDescription": "Tree Organization Chart",
"BasicGroupName": "Properties", "BasicGroupName": "Properties",
"TitleFieldLabel": "WebPart Title", "TitleFieldLabel": "WebPart Title",
"CurrentUserTeamFieldLabel": "Show only my team ?", "MaxLevels": "Max Depth",
"MaxLevels": "Max Depth" "ViewType": "View options",
"TreeOrgChartTypeMyTeam": "Show my team",
"TreeOrgChartTypeCompany": "Show company hirachy",
"TreeOrgChartTypeShowOtherTeam": "Show other team",
"FilterGroupName":"Account Name Filter",
"ExcludeFilter": "Filter Logic",
"ExcludeFilterOnText": "Exclude",
"ExcludeFilterOffText": "Include",
"FilterLabel": "Filter (contains)",
"FilterDescription": "currently only contains or not contains filter logic can be switched with the toggle above",
"TeamLeaderHeadline":"Please Select a Teamleader",
"ContactInfoTitle":"Contact Info",
"DetailBehavoir":"Detail link behavior ",
"LivePersonaCard":"Live Persona Card",
"DelveLink":"Link to Delve"
} }
}); });

View File

@ -2,8 +2,24 @@ declare interface ITreeOrgChartWebPartStrings {
PropertyPaneDescription: string; PropertyPaneDescription: string;
BasicGroupName: string; BasicGroupName: string;
TitleFieldLabel: string; TitleFieldLabel: string;
CurrentUserTeamFieldLabel:string;
MaxLevels: string; MaxLevels: string;
ViewType: string;
TreeOrgChartTypeMyTeam: string;
TreeOrgChartTypeCompany: string;
TreeOrgChartTypeShowOtherTeam: string;
FilterGroupName:string;
ExcludeFilter: string;
ExcludeFilterOnText: string;
ExcludeFilterOffText: string;
FilterLabel: string;
FilterDescription: string;
TeamLeaderHeadline:string;
ContactInfoTitle:string;
DetailBehavoir:string;
LivePersonaCard:string;
DelveLink:string;
} }
declare module 'TreeOrgChartWebPartStrings' { declare module 'TreeOrgChartWebPartStrings' {