diff --git a/samples/react-tree-orgchart/README.md b/samples/react-tree-orgchart/README.md index 9b6fc39d0..da192325f 100644 --- a/samples/react-tree-orgchart/README.md +++ b/samples/react-tree-orgchart/README.md @@ -3,15 +3,20 @@ ## 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. -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/Screenshot2.png) ![Organization Chart Web Part](./assets/Screenshot3.png) + ## Used SharePoint Framework Version ![drop](https://img.shields.io/badge/version-1.10.0-green.svg) @@ -26,24 +31,37 @@ We can configure in the webpart properties if it show all Organization Chart or Property |Type|Required| comments --------------------|----|--------|---------- -WebPart Title| Text| no| -Show Only My Team| Boolean | true -MaxDepth | Number| yes | Maximum number of levels to show +title | Text| no| WebPart Title +teamLeader |Text|no|UPN of manager if viewType is 4 +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|Author(s) --------|--------- Tree Organization WebPart|João Mendes +Tree Organization WebPart|Peter Paul Kirschner ([@petkir_at](https://twitter.com/petkir_at)) ## Version history Version|Date|Comments -------|----|-------- -1.0.2|June 12, 2020|Added exception handler for profiles missing display name +1.1.0|Feb 28, 2021|Added +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.0|Feb 25, 2019|Initial release +1.0.0|Feb 25, 2019|Initial release ## Disclaimer **THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.** diff --git a/samples/react-tree-orgchart/assets/react-tree-orgchart.gif b/samples/react-tree-orgchart/assets/react-tree-orgchart.gif new file mode 100644 index 000000000..73820c25f Binary files /dev/null and b/samples/react-tree-orgchart/assets/react-tree-orgchart.gif differ diff --git a/samples/react-tree-orgchart/config/package-solution.json b/samples/react-tree-orgchart/config/package-solution.json index a41e1cf19..d834e65d8 100644 --- a/samples/react-tree-orgchart/config/package-solution.json +++ b/samples/react-tree-orgchart/config/package-solution.json @@ -3,7 +3,7 @@ "solution": { "name": "react-tree-orgchart-client-side-solution", "id": "d76a0c4f-d669-42eb-9533-68d5cec5e9d3", - "version": "1.0.2.0", + "version": "1.1.0.0", "includeClientSideAssets": true, "skipFeatureDeployment": true, "isDomainIsolated": false diff --git a/samples/react-tree-orgchart/package-lock.json b/samples/react-tree-orgchart/package-lock.json index a7c92a460..23c8b4109 100644 --- a/samples/react-tree-orgchart/package-lock.json +++ b/samples/react-tree-orgchart/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-tree-orgchart", - "version": "0.0.1", + "version": "1.0.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2265,9 +2265,9 @@ } }, "@microsoft/microsoft-graph-types": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-1.5.0.tgz", - "integrity": "sha512-eit9LMlhHLyzCByATGL8d7izWNRVBlzrPMfXqy2a9qIVUUNIGxyqkGJNrpEh3EVDXW2r+/ASsBAqzHkm8zWJiQ==" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-1.7.0.tgz", + "integrity": "sha512-Mxu5H+69F8T5NzV4+U8FkTvpIYYWHsmRZzfAuOlIO0zJJGlVyRIVqpq4NmOdUXGC00vZ73ONgCuzuaksxqDm/Q==" }, "@microsoft/node-core-library": { "version": "3.15.1", @@ -4013,12 +4013,12 @@ } }, "@pnp/common": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@pnp/common/-/common-1.2.9.tgz", - "integrity": "sha512-wVu8yJZvdnN99hhpmHxhK0HbUVMg61y8o8vC2w3MK+nql65GH9YaxkDQotNSKlYjDakzG/HYa8cZW3TIaCFPcg==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@pnp/common/-/common-1.3.11.tgz", + "integrity": "sha512-RhYKcfMP+h0pAzORZRHSPPLOBB58djN/pfnorpWPjsx6ZxMqbiDqTzAtTF4m8z/mdNnxJr0Q3kwt4ImU3FjwnA==", "requires": { "adal-angular": "1.0.17", - "tslib": "1.9.3" + "tslib": "1.10.0" }, "dependencies": { "adal-angular": { @@ -4027,118 +4027,119 @@ "integrity": "sha1-bpNuDkH5HTsqiOf/ypwvb29WLMQ=" }, "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" } } }, "@pnp/graph": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@pnp/graph/-/graph-1.2.9.tgz", - "integrity": "sha512-n1aH2HWmXXc0ZRBTnU9U3oz5Vua7jzw+zjRhkdQYh+AAnBcVD2drT+CaAJNB9RND5SpzajJ31GR+0cmDx7J2qw==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@pnp/graph/-/graph-1.3.11.tgz", + "integrity": "sha512-AbJdiCdI+SZTk7LI0NP5snw8D0udQWQbFRhCmI1e+j6k/Wt/FYEfXkgiAqXKc+f8+PpUtt1/ezab3sbrxs9btA==", "requires": { - "@microsoft/microsoft-graph-types": "1.5.0", - "tslib": "1.9.3" + "@microsoft/microsoft-graph-types": "1.7.0", + "tslib": "1.10.0" }, "dependencies": { "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" } } }, "@pnp/logging": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@pnp/logging/-/logging-1.2.9.tgz", - "integrity": "sha512-JNxoHkPhPnnC1PHnU+wQVkDkaBzrskDvLHn7bq84Uz+ppZEnKp0IuOxvmkAPMwD1NVP5qRbbiBh7dIHu8b9rNw==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@pnp/logging/-/logging-1.3.11.tgz", + "integrity": "sha512-hADlIXwvF/wjee7425nFJ6NhqaWpWTJ5yg02bpwBUsiSuFqEUf+LwuAcyHQre2lMs6KyNa65FWoRQok9BlZuxA==", "requires": { - "tslib": "1.9.3" + "tslib": "1.10.0" }, "dependencies": { "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" } } }, "@pnp/odata": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@pnp/odata/-/odata-1.2.9.tgz", - "integrity": "sha512-mE4bY5PQXxNYJIyh5Mgqda4AeX5DWEjT9NuUH7G05JOKwV51DbUX+UPIIy7AqBXDjo05S3QvOJw6+4OfeMQuZQ==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@pnp/odata/-/odata-1.3.11.tgz", + "integrity": "sha512-yMaRiuVZRei2pkryCOqsw3ZXD2Lw30IJv136WQmQPQPOxG4cvsS9+woXkfMqbWV2KQ1evFUqVXbitIz6eDVfNA==", "requires": { - "tslib": "1.9.3" + "tslib": "1.10.0" }, "dependencies": { "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" } } }, "@pnp/sp": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@pnp/sp/-/sp-1.2.9.tgz", - "integrity": "sha512-O+V/IrI/dqDtc/d42HsTlPbqNqLut6/UiTkWwuZMwbhJeNmb9S/CyygTaa2luyvVw2UaVa1x70zdoslxU0Itew==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@pnp/sp/-/sp-1.3.11.tgz", + "integrity": "sha512-NjdeGe81aukiSPelSPjgAFRC1+SrNPTXvTdEqTH+Q1ZvgNtk8bdZp6K6xf9emfeM2qZDOu9GpKZpg0W/emq++g==", "requires": { - "tslib": "1.9.3" + "tslib": "1.10.0" }, "dependencies": { "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" } } }, "@pnp/sp-clientsvc": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@pnp/sp-clientsvc/-/sp-clientsvc-1.2.9.tgz", - "integrity": "sha512-zaInYyQgbyk5a4+2KMr9qHRKHexqRQMiQk5eu6SM6fIEVyC5H422Tr5WREVzNTMp4YVl8MKuXkeTNxLhG7iTJQ==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@pnp/sp-clientsvc/-/sp-clientsvc-1.3.11.tgz", + "integrity": "sha512-eIUnmDWjizcWJzhWxAbfsxEyHF1dabkGlihnDnlcYGhtvh8BwuM67A57qc5fbxzCS59c0YU57szB1EucoNmV4A==", "requires": { - "tslib": "1.9.3" + "tslib": "1.10.0" }, "dependencies": { "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" } } }, "@pnp/sp-taxonomy": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@pnp/sp-taxonomy/-/sp-taxonomy-1.2.9.tgz", - "integrity": "sha512-pJCuikAI2ntplc1VoyIo5wbe2F44t9B6sA66L7LqOPc/i+qU8ywjkelHznmshUomOzPycuFXqwgYcnHyxJVCXw==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@pnp/sp-taxonomy/-/sp-taxonomy-1.3.11.tgz", + "integrity": "sha512-shzCSjmOlr6mojCXJkfD8Xf9lJnhphq4Fj6mdUQGwpak+VIU+Fogf6AI0j6AReCKtKsKyqfud9X7C8tH07C3DA==", "requires": { - "tslib": "1.9.3" + "tslib": "1.10.0" }, "dependencies": { "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" } } }, "@pnp/spfx-controls-react": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@pnp/spfx-controls-react/-/spfx-controls-react-1.11.0.tgz", - "integrity": "sha512-7i2g3l95/CXpiugfM8V0m8aEHeyoRFBlTiZfoQiue5LW9O3XC+okDSbf8vOBNgddYTRLnRZKEo/TMKcuNEi3zQ==", + "version": "1.21.1", + "resolved": "https://registry.npmjs.org/@pnp/spfx-controls-react/-/spfx-controls-react-1.21.1.tgz", + "integrity": "sha512-HpBZtrtNfAMn9vySTEZutFovnwiYGg7skptLhf2gZmhSOUIBB0THweBRTDPqT8zBSkxc1ffVHAOArVgaMb+zMQ==", "requires": { "@pnp/common": "1.0.1", "@pnp/logging": "1.0.1", "@pnp/odata": "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", "chart.js": "2.7.3", - "color": "^3.1.0", - "lodash": "4.17.4", - "office-ui-fabric-react": "5.131.0" + "color": "^3.1.2", + "lodash": "4.17.13", + "office-ui-fabric-react": "5.131.0", + "react-quill": "1.3.3" }, "dependencies": { "@pnp/common": { @@ -4173,35 +4174,30 @@ "tslib": "1.8.1" } }, - "color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.0.tgz", - "integrity": "sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg==", + "@pnp/telemetry-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@pnp/telemetry-js/-/telemetry-js-2.0.0.tgz", + "integrity": "sha512-qFNm3mTerTnxgTR6c/4iMMt8EUKrQn5z0XG/IQtpNlp6m7KXRDFR87mQKeBVtSv2LhxGO0VNFndKJIibBw52zQ==", "requires": { - "color-convert": "^1.9.1", - "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" + "whatwg-fetch": "2.0.4" } }, "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.13.tgz", + "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": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@pnp/spfx-property-controls/-/spfx-property-controls-1.14.1.tgz", - "integrity": "sha512-GN3mmqpBJtOJJX/tCYXU1SZPCm25HGFfLkhRo+C3PEZ7NzmpbLqaIjrMD2ePG4C+UEkKOubmh1sn/9LiYNtOSg==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@pnp/spfx-property-controls/-/spfx-property-controls-1.20.0.tgz", + "integrity": "sha512-+V7IUNHABJd62lXZzyDbqBqZVeeHBPuy1L+X98aIa2pagCvSuDNQOz6MHvP6iGExTK+MrSB0XgZZk1u4kfz6BQ==", "requires": { "@pnp/common": "^1.2.8", "@pnp/logging": "^1.2.8", @@ -4209,15 +4205,17 @@ "@pnp/sp": "^1.2.8", "@pnp/sp-clientsvc": "^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", "react-ace": "5.8.0" } }, "@pnp/telemetry-js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@pnp/telemetry-js/-/telemetry-js-1.0.0.tgz", - "integrity": "sha512-7Lr22EB6DgB8MZi0WDuou8VuXru3wHdiOQPenB2B2gdhp7bJj2ijN9vTiqF8aL1nh80uJxIyX269Ix/PSnJC7g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@pnp/telemetry-js/-/telemetry-js-2.0.0.tgz", + "integrity": "sha512-qFNm3mTerTnxgTR6c/4iMMt8EUKrQn5z0XG/IQtpNlp6m7KXRDFR87mQKeBVtSv2LhxGO0VNFndKJIibBw52zQ==", "requires": { "whatwg-fetch": "2.0.4" }, @@ -4525,6 +4523,14 @@ "integrity": "sha1-aQoUdbhPKohP0HzXl8APXzE1bqg=", "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": { "version": "0.25.51", "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" } }, + "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": { "version": "2.0.0", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -6926,25 +6941,18 @@ } }, "chartjs-color": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.2.0.tgz", - "integrity": "sha1-hKL7dVeH7YXDndbdjHsdiEKbrq4=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", + "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", "requires": { - "chartjs-color-string": "^0.5.0", - "color-convert": "^0.5.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": "^0.6.0", + "color-convert": "^1.9.3" } }, "chartjs-color-string": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz", - "integrity": "sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", + "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", "requires": { "color-name": "^1.0.0" } @@ -7247,7 +7255,6 @@ "version": "3.1.2", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/color/-/color-3.1.2.tgz", "integrity": "sha1-aBSOf4XUGtdknF+oyBBvCY0inhA=", - "dev": true, "requires": { "color-convert": "^1.9.1", "color-string": "^1.5.2" @@ -7270,7 +7277,6 @@ "version": "1.5.3", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/color-string/-/color-string-1.5.3.tgz", "integrity": "sha1-ybvF8BtYtUkvPWhXRZy2WQziBMw=", - "dev": true, "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -7558,6 +7564,15 @@ "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": { "version": "6.0.5", "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" } }, + "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": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -8166,7 +8194,6 @@ "version": "1.1.3", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", - "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -9214,6 +9241,11 @@ "through": "^2.3.8" } }, + "eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", + "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=" + }, "events": { "version": "3.1.0", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/events/-/events-3.1.0.tgz", @@ -9453,8 +9485,7 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { "version": "3.0.2", @@ -9577,6 +9608,11 @@ "integrity": "sha1-VFFFB3xQFJHjOxXsQIwpQ3bpSuQ=", "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": { "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", @@ -10111,7 +10147,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -10132,12 +10169,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -10152,17 +10191,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -10279,7 +10321,8 @@ "inherits": { "version": "2.0.4", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -10291,6 +10334,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -10305,6 +10349,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -10312,12 +10357,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -10336,6 +10383,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -10425,7 +10473,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -10437,6 +10486,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -10522,7 +10572,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -10558,6 +10609,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -10577,6 +10629,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -10620,12 +10673,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -10644,8 +10699,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", - "dev": true + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" }, "functional-red-black-tree": { "version": "1.0.1", @@ -10713,6 +10767,16 @@ "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=", "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": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -11331,7 +11395,6 @@ "version": "1.0.3", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/has/-/has-1.0.3.tgz", "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -11363,8 +11426,7 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha1-n1IUdYpEGWxAbZvXbOv4HsLdMeg=", - "dev": true + "integrity": "sha1-n1IUdYpEGWxAbZvXbOv4HsLdMeg=" }, "has-unicode": { "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": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -12077,8 +12147,7 @@ "is-date-object": { "version": "1.0.2", "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=", - "dev": true + "integrity": "sha1-vac28s2P0G0yhE53Q7+nSUw7/X4=" }, "is-descriptor": { "version": "0.1.6", @@ -12252,7 +12321,6 @@ "version": "1.0.5", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/is-regex/-/is-regex-1.0.5.tgz", "integrity": "sha1-OdWJo1i/GJZ/cmlnEguPwa7XTq4=", - "dev": true, "requires": { "has": "^1.0.3" } @@ -14833,6 +14901,11 @@ "integrity": "sha1-VYqlO0O2YeGSWgr9+japoQhf5Xo=", "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": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", @@ -15015,6 +15088,15 @@ "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": { "version": "2.0.0", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/matchdep/-/matchdep-2.0.0.tgz", @@ -15381,9 +15463,9 @@ } }, "moment": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" }, "move-concurrently": { "version": "1.0.1", @@ -15950,11 +16032,19 @@ "integrity": "sha1-9Pa9GBrXfwBrXs5gvQtvOY/3Smc=", "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": { "version": "1.1.1", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=", - "dev": true + "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=" }, "object-visit": { "version": "1.0.1", @@ -16369,6 +16459,11 @@ "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": { "version": "1.0.1", "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=", "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": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", @@ -17755,6 +17880,11 @@ "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": { "version": "16.8.2", "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", "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": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/react-sortable-tree/-/react-sortable-tree-2.6.0.tgz", @@ -18022,6 +18173,15 @@ "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": { "version": "2.0.1", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/regexpp/-/regexpp-2.0.1.tgz", @@ -20479,8 +20639,7 @@ "unquote": { "version": "1.1.1", "resolved": "https://admdev.pkgs.visualstudio.com/_packaging/Artifacts/npm/registry/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", - "dev": true + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=" }, "unset-value": { "version": "1.0.0", diff --git a/samples/react-tree-orgchart/package.json b/samples/react-tree-orgchart/package.json index d56945163..1184a06e8 100644 --- a/samples/react-tree-orgchart/package.json +++ b/samples/react-tree-orgchart/package.json @@ -1,6 +1,6 @@ { "name": "react-tree-orgchart", - "version": "1.0.2", + "version": "1.1.0", "private": true, "engines": { "node": ">=0.10.0" @@ -15,13 +15,13 @@ "@microsoft/sp-lodash-subset": "1.10.0", "@microsoft/sp-office-ui-fabric-core": "1.10.0", "@microsoft/sp-webpart-base": "1.10.0", - "@pnp/common": "^1.2.9", - "@pnp/graph": "^1.2.9", - "@pnp/logging": "^1.2.9", - "@pnp/odata": "^1.2.9", - "@pnp/sp": "^1.2.9", - "@pnp/spfx-controls-react": "^1.11.0", - "@pnp/spfx-property-controls": "^1.14.1", + "@pnp/common": "1.3.11", + "@pnp/graph": "1.3.11", + "@pnp/logging": "1.3.11", + "@pnp/odata": "1.3.11", + "@pnp/sp": "1.3.11", + "@pnp/spfx-controls-react": "1.21.1", + "@pnp/spfx-property-controls": "1.20.0", "@types/es6-promise": "0.0.33", "@types/react": "16.4.2", "@types/react-dom": "16.0.5", diff --git a/samples/react-tree-orgchart/src/services/GraphService.ts b/samples/react-tree-orgchart/src/services/GraphService.ts new file mode 100644 index 000000000..3abe26273 --- /dev/null +++ b/samples/react-tree-orgchart/src/services/GraphService.ts @@ -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 { + + return await graph.users.getById(upn).select(...graphUserSelect).get() as IGraphUser; + } + + public async getUserManger(upn: string): Promise { + + 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; + + } + +} + diff --git a/samples/react-tree-orgchart/src/webparts/treeOrgChart/TreeOrgChartWebPart.manifest.json b/samples/react-tree-orgchart/src/webparts/treeOrgChart/TreeOrgChartWebPart.manifest.json index e0406269c..5355d46d1 100644 --- a/samples/react-tree-orgchart/src/webparts/treeOrgChart/TreeOrgChartWebPart.manifest.json +++ b/samples/react-tree-orgchart/src/webparts/treeOrgChart/TreeOrgChartWebPart.manifest.json @@ -12,7 +12,7 @@ // 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 "requiresCustomScript": false, - +//"viewType": 1, "preconfiguredEntries": [{ "groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other "group": { "default": "Other" }, @@ -22,6 +22,7 @@ "properties": { "title": "My Team Organization Chart", "currentUserTeam": true, + "maxLevels": 5 } }] diff --git a/samples/react-tree-orgchart/src/webparts/treeOrgChart/TreeOrgChartWebPart.ts b/samples/react-tree-orgchart/src/webparts/treeOrgChart/TreeOrgChartWebPart.ts index c982a51e2..696b2e598 100644 --- a/samples/react-tree-orgchart/src/webparts/treeOrgChart/TreeOrgChartWebPart.ts +++ b/samples/react-tree-orgchart/src/webparts/treeOrgChart/TreeOrgChartWebPart.ts @@ -1,36 +1,48 @@ import * as React from 'react'; import * as ReactDom from 'react-dom'; import { Version } from '@microsoft/sp-core-library'; -import { - BaseClientSideWebPart, - IPropertyPaneConfiguration, - PropertyPaneTextField, - PropertyPaneToggle -} from '@microsoft/sp-webpart-base'; + import * as strings from 'TreeOrgChartWebPartStrings'; -import TreeOrgChart from './components/TreeOrgChart'; +import TreeOrgChart, { TreeOrgChartType } from './components/TreeOrgChart'; import { ITreeOrgChartProps } from './components/ITreeOrgChartProps'; import { PropertyFieldNumber } from '@pnp/spfx-property-controls/lib/PropertyFieldNumber'; 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 { title: string; currentUserTeam: boolean; + teamLeader: string; maxLevels: number; + viewType: TreeOrgChartType; + filter: string; + excludefilter: boolean; + detailBehavoir: boolean; } + + export default class TreeOrgChartWebPart extends BaseClientSideWebPart { public onInit(): Promise { pnpSetup({ 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(); } public render(): void { + const element: React.ReactElement = React.createElement( TreeOrgChart, { @@ -39,8 +51,16 @@ export default class TreeOrgChartWebPart extends BaseClientSideWebPart { 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, + filter: this.properties.filter, + excludefilter: this.properties.excludefilter, + detailBehavoir: this.properties.detailBehavoir, context: this.context } ); @@ -70,9 +90,16 @@ export default class TreeOrgChartWebPart extends BaseClientSideWebPart void; + viewType: TreeOrgChartType; + teamLeader?: string; + updateTeamLeader: (loginname: string) => void; context: WebPartContext; + filter: string; + excludefilter: boolean; + detailBehavoir: boolean; } diff --git a/samples/react-tree-orgchart/src/webparts/treeOrgChart/components/ITreeOrgChartState.ts b/samples/react-tree-orgchart/src/webparts/treeOrgChart/components/ITreeOrgChartState.ts index ece6bf094..8db0b49d2 100644 --- a/samples/react-tree-orgchart/src/webparts/treeOrgChart/components/ITreeOrgChartState.ts +++ b/samples/react-tree-orgchart/src/webparts/treeOrgChart/components/ITreeOrgChartState.ts @@ -1,4 +1,5 @@ export interface ITreeOrgChartState { treeData: any; isLoading: boolean; + livePersonaCard?: any; } diff --git a/samples/react-tree-orgchart/src/webparts/treeOrgChart/components/TreeOrgChart.tsx b/samples/react-tree-orgchart/src/webparts/treeOrgChart/components/TreeOrgChart.tsx index 346838466..ad85dc6f9 100755 --- a/samples/react-tree-orgchart/src/webparts/treeOrgChart/components/TreeOrgChart.tsx +++ b/samples/react-tree-orgchart/src/webparts/treeOrgChart/components/TreeOrgChart.tsx @@ -16,24 +16,39 @@ import { import { IconButton } from "office-ui-fabric-react/lib/Button"; import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle"; import SPService from "../../../services/SPServices"; -import { ITreeChildren } from "./ITreeChildren"; import { ITreeData } from "./ITreeData"; import { Spinner, SpinnerSize } 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< ITreeOrgChartProps, ITreeOrgChartState -> { + > { private treeData: ITreeData[]; private SPService: SPService; + private GraphService: GraphService; constructor(props) { super(props); this.SPService = new SPService(this.props.context); + this.GraphService = new GraphServices(this.props.context); this.state = { treeData: [], isLoading: true @@ -49,43 +64,97 @@ export default class TreeOrgChart extends React.Component< prevState: ITreeOrgChartState ) { if ( - this.props.currentUserTeam !== prevProps.currentUserTeam || - this.props.maxLevels !== prevProps.maxLevels + this.props.viewType !== prevProps.viewType || + 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(); } } 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(); } + + private async _loadSPComponentById(componentId: string): Promise { + 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 */ public async loadOrgchart() { + this.setState({ treeData: [], isLoading: true }); - const currentUser = `i:0#.f|membership|${this.props.context.pageContext.user.loginName}`; - const currentUserProperties = await this.SPService.getUserProperties( - currentUser - ); + const currentUser = this.props.context.pageContext.user.loginName; + let currentUserProperties = null; this.treeData = []; // Test if show only my Team or All Organization Chart - if (!this.props.currentUserTeam) { - const treeManagers = await this.buildOrganizationChart( - currentUserProperties - ); - if (treeManagers) this.treeData.push(treeManagers); - } else { - const treeManagers = await this.buildMyTeamOrganizationChart( - currentUserProperties - ); - if (treeManagers) - this.treeData.push({ - title: treeManagers.person, - expanded: true, - children: treeManagers.treeChildren - }); + 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( + currentUserProperties + ); + if (treeManagers) this.treeData.push(treeManagers); + break; + case TreeOrgChartType.MyTeam: + const myteam = await this.buildMyTeamOrganizationChart( + currentUser + ); + if (myteam) + this.treeData = [{ ...myteam }]; + break; + case TreeOrgChartType.ShowOtherTeam: + 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 }); } @@ -100,185 +169,131 @@ export default class TreeOrgChart extends React.Component< currentUserProperties.ExtendedManagers && currentUserProperties.ExtendedManagers.length > 0 ) { - treeManagers = await this.getUsers( - currentUserProperties.ExtendedManagers[0] - ); + const upn: string | undefined = this.claimUserToUPN(currentUserProperties.ExtendedManagers[0]); + if (upn) { + treeManagers = await this.getUsers( + upn + ); + } + } return treeManagers; } - /* - // Get user from Top Manager - */ - private async getUsers(manager: string) { - let person: any; + + private claimUserToUPN(claim: string): string | undefined { + if (!claim) { return undefined; } + const claimuser: string[] = claim.split('|'); + 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 = {}; - // Get User Properties - const managerProperties = await this.SPService.getUserProperties(manager); - - - let imageInitials: string[] = managerProperties.DisplayName.split(" "); - + let imageInitials: string[] = user.displayName ? user.displayName.split(" ") : []; + //https://graph.microsoft.com/v1.0/users/${upn}/photo/$value // Persona Card Properties - spUser.imageUrl = `/_layouts/15/userphoto.aspx?size=L&username=${managerProperties.Email}`; - spUser.imageInitials = imageInitials && imageInitials.length > 0 ? `${imageInitials[0] + spUser.imageUrl = user.userPrincipalName ? `/_layouts/15/userphoto.aspx?size=L&username=${user.userPrincipalName}` : undefined; + 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; + .toUpperCase()}${imageInitials[1] ? imageInitials[1].substring(0, 1).toUpperCase() : ''}` : ''; + spUser.text = user.displayName; + spUser.tertiaryText = user.mail; + spUser.secondaryText = user.jobTitle; // PersonaCard component - person = ( + return ( ); - // Has DirectReports - if ( - managerProperties.DirectReports && - managerProperties.DirectReports.length > 0 - ) { - const usersDirectReports: any[] = await this.getChildren( - managerProperties.DirectReports - ); - // return treeData - return { title: person, expanded: true, children: usersDirectReports }; - // Don't have DirectReports + } + + + private async getUsers(upn: string): Promise { + const managerUser = await this.GraphService.getUser(upn); + const person = this.buildPersonaCard(managerUser); + if (managerUser.userPrincipalName) { + return ({ + title: person, + expanded: true, + children: await this.getDirectReportsUsers(managerUser.userPrincipalName) + }); } else { - // return treeData return { title: person }; } } - // Get Children (user DirectReports) - private async getChildren(userDirectReports: any[]) { - let treeChildren: ITreeChildren[] = []; - let spUser: IPersonaSharedProps = {}; - for (const user of userDirectReports) { - const managerProperties = await this.SPService.getUserProperties(user); - const imageInitials: string[] = managerProperties.DisplayName.split(" "); + private async getDirectReportsUsers(upn?: string, level: number = 1, expanded: boolean = false): Promise { + if (!upn) { return null; } - 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 = ( - - ); - const usersDirectReports = await this.getChildren( - managerProperties.DirectReports - ); + + const directReportsUser = await this.GraphService.getUserDirectReports(upn,this.props.excludefilter,this.props.filter); + //this is already level 1 + 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 + }); - usersDirectReports - ? treeChildren.push({ title: person, children: usersDirectReports }) - : treeChildren.push({ title: person }); + })); } - return treeChildren; + return null; } + + + //buildTeamLeaderOrganizationChart + private async buildTeamLeaderOrganizationChart(upn: string): Promise { + + const tmpupn: string | undefined = this.claimUserToUPN(upn); + + return await this.getUsers(tmpupn ? tmpupn : upn); + + } /* Build My Team Organization Chart @parm: currentUserProperties */ - private async buildMyTeamOrganizationChart(currentUserProperties: any) { - 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 = ( - - ); - hasManager = true; - } + private async buildMyTeamOrganizationChart(upn: string): Promise { - // Get my Properties - const meImageInitials: string[] = currentUserProperties.DisplayName.split( - " " - ); - 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 = ( - - ); - 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; + const mymanager = await this.GraphService.getUserManger(upn); + if (mymanager && mymanager.userPrincipalName) { + return await this.getUsers(mymanager.userPrincipalName); } - - // 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 = ( - - ); - treeChildren.push({ title: peerCard }); - } - // Return - return { person: managerCard, treeChildren: treeChildren }; + return await this.getUsers(upn); } // Render public render(): React.ReactElement { + 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 (
+ {showEditOther && (
+ { + 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} /> +
)} + {this.state.isLoading ? ( ({ - buttons: [ - { - window.open( - `https://eur.delve.office.com/?p=${rowInfo.node.title.props.tertiaryText}&v=work` - ); - }} - /> - ] - })} + generateNodeProps={rowInfo => { + return !this.props.detailBehavoir ? + ({ + buttons: [ + { + window.open( + `https://eur.delve.office.com/?p=${rowInfo.node.title.props.tertiaryText}&v=work` + ); + }} + /> + ] + }) : undefined; + } + } />
diff --git a/samples/react-tree-orgchart/src/webparts/treeOrgChart/loc/en-us.js b/samples/react-tree-orgchart/src/webparts/treeOrgChart/loc/en-us.js index 364f657b9..ffa266ae1 100644 --- a/samples/react-tree-orgchart/src/webparts/treeOrgChart/loc/en-us.js +++ b/samples/react-tree-orgchart/src/webparts/treeOrgChart/loc/en-us.js @@ -3,7 +3,21 @@ define([], function () { "PropertyPaneDescription": "Tree Organization Chart", "BasicGroupName": "Properties", "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" } }); diff --git a/samples/react-tree-orgchart/src/webparts/treeOrgChart/loc/mystrings.d.ts b/samples/react-tree-orgchart/src/webparts/treeOrgChart/loc/mystrings.d.ts index 2e3a3001b..f85acf450 100644 --- a/samples/react-tree-orgchart/src/webparts/treeOrgChart/loc/mystrings.d.ts +++ b/samples/react-tree-orgchart/src/webparts/treeOrgChart/loc/mystrings.d.ts @@ -2,8 +2,24 @@ declare interface ITreeOrgChartWebPartStrings { PropertyPaneDescription: string; BasicGroupName: string; TitleFieldLabel: string; - CurrentUserTeamFieldLabel: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' {