diff --git a/samples/react-graph-profile-awards/README.md b/samples/react-graph-profile-awards/README.md index ef0879362..ae0f52e0a 100644 --- a/samples/react-graph-profile-awards/README.md +++ b/samples/react-graph-profile-awards/README.md @@ -2,11 +2,15 @@ ## Summary -This web part is using the beta MS Graph Profile endpoint to list your awards. At the time of writing this sample (May 2022), this is a Beta endpoint, so it could change in the future. A future version of this web part could include the ability to add new awards to your profile. +This web part is using the beta MS Graph Profile endpoint to list user's profile awards. At the time of writing this sample (May 2022), this is a Beta endpoint, so it could change in the future. You can select the user you want to get their profile awards. It allows to configure different options. You can the user selecting it from a People picker, or from a Page environment variable (using Dynamic field), or just selecting the current logged user. It also allows two different layout options, so it can render the awards using cards, or in a list format. + +A future version of this web part could include the ability to add new awards to your profile. In the meantime, you can add a new award using this request: [https://docs.microsoft.com/en-us/graph/api/profile-post-awards?view=graph-rest-beta&tabs=http](https://docs.microsoft.com/en-us/graph/api/profile-post-awards?view=graph-rest-beta&tabs=http) (You can use [Graph Explorer](https://developer.microsoft.com/en-us/graph/graph-explorer) tool to do so.) -![my-awards](./assets/react-graph-profile-awards.png) +__Note__: when adding a new award, ensure you set the field __allowedAudiences__ to a proper value (organization / everyone). Otherwise, the award is only visible for the user who owns it. + +![Awards](./assets/react-graph-profile-awards.gif) ## Compatibility @@ -28,7 +32,7 @@ In the meantime, you can add a new award using this request: [https://docs.micro ## Prerequisites -You need to grant any of these permissions to MS Graph API (from least to most privileged): _User.Read, User.ReadWrite, User.ReadBasic.All, User.Read.All, User.ReadWrite.All_ +You need to grant these permissions to MS Graph API (from least to most privileged): _User.Read, User.Read.All_ Suggest you to use the [Microsoft 365 CLI](https://blog.mastykarz.nl/grant-api-permissions-office-365-cli/) @@ -43,6 +47,7 @@ Suggest you to use the [Microsoft 365 CLI](https://blog.mastykarz.nl/grant-api-p | Version | Date | Comments | | ------- | ---------------- | --------------- | | 1.0 | May 23, 2022 | Initial release | +| 1.1 | Aug 06, 2022 | User selector from different origins (People picker, Page environment variable). Also has 2 different layouts for rendering the awards | ## Minimal Path to Awesome diff --git a/samples/react-graph-profile-awards/assets/react-graph-profile-awards.gif b/samples/react-graph-profile-awards/assets/react-graph-profile-awards.gif new file mode 100644 index 000000000..8a114ffc3 Binary files /dev/null and b/samples/react-graph-profile-awards/assets/react-graph-profile-awards.gif differ diff --git a/samples/react-graph-profile-awards/assets/react-graph-profile-awards.png b/samples/react-graph-profile-awards/assets/react-graph-profile-awards.png deleted file mode 100644 index 5c8bad555..000000000 Binary files a/samples/react-graph-profile-awards/assets/react-graph-profile-awards.png and /dev/null differ diff --git a/samples/react-graph-profile-awards/config/config.json b/samples/react-graph-profile-awards/config/config.json index 64fc22048..7dfe944a7 100644 --- a/samples/react-graph-profile-awards/config/config.json +++ b/samples/react-graph-profile-awards/config/config.json @@ -13,6 +13,7 @@ }, "externals": {}, "localizedResources": { - "MyAwardsWebPartStrings": "lib/webparts/myAwards/loc/{locale}.js" + "MyAwardsWebPartStrings": "lib/webparts/myAwards/loc/{locale}.js", + "PropertyControlStrings": "node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js" } -} +} \ No newline at end of file diff --git a/samples/react-graph-profile-awards/package-lock.json b/samples/react-graph-profile-awards/package-lock.json index e412a0de9..18134418d 100644 --- a/samples/react-graph-profile-awards/package-lock.json +++ b/samples/react-graph-profile-awards/package-lock.json @@ -3309,6 +3309,14 @@ } } }, + "@monaco-editor/loader": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.3.2.tgz", + "integrity": "sha512-BTDbpHl3e47r3AAtpfVFTlAi7WXv4UQ/xZmz8atKl4q7epQV5e7+JbigFDViWF71VBi4IIBdcWP57Hj+OWuc9g==", + "requires": { + "state-local": "^1.0.6" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3396,6 +3404,601 @@ "integrity": "sha512-GtwNB6BNDdsIPAYEdpp3JnOGO/3AJxjPvny53s3HERBdXSJTGQw8IRhiaTEX0b3w9P8+FwFZde4k+qkjn67aVw==", "dev": true }, + "@pnp/common": { + "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.10.0" + }, + "dependencies": { + "adal-angular": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/adal-angular/-/adal-angular-1.0.17.tgz", + "integrity": "sha512-+Z9aq7L25OncsaVcnhSsi7AMR/dlg0gWVNptsdtkL9Ih7hA1oJ14mhWB60CB83JF6DlzamVKLMGbrAcgFQqhCg==" + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@pnp/logging": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@pnp/logging/-/logging-1.3.11.tgz", + "integrity": "sha512-hADlIXwvF/wjee7425nFJ6NhqaWpWTJ5yg02bpwBUsiSuFqEUf+LwuAcyHQre2lMs6KyNa65FWoRQok9BlZuxA==", + "requires": { + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@pnp/odata": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@pnp/odata/-/odata-1.3.11.tgz", + "integrity": "sha512-yMaRiuVZRei2pkryCOqsw3ZXD2Lw30IJv136WQmQPQPOxG4cvsS9+woXkfMqbWV2KQ1evFUqVXbitIz6eDVfNA==", + "requires": { + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@pnp/sp": { + "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.10.0" + }, + "dependencies": { + "tslib": { + "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.3.11", + "resolved": "https://registry.npmjs.org/@pnp/sp-clientsvc/-/sp-clientsvc-1.3.11.tgz", + "integrity": "sha512-eIUnmDWjizcWJzhWxAbfsxEyHF1dabkGlihnDnlcYGhtvh8BwuM67A57qc5fbxzCS59c0YU57szB1EucoNmV4A==", + "requires": { + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "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.3.11", + "resolved": "https://registry.npmjs.org/@pnp/sp-taxonomy/-/sp-taxonomy-1.3.11.tgz", + "integrity": "sha512-shzCSjmOlr6mojCXJkfD8Xf9lJnhphq4Fj6mdUQGwpak+VIU+Fogf6AI0j6AReCKtKsKyqfud9X7C8tH07C3DA==", + "requires": { + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@pnp/spfx-property-controls": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@pnp/spfx-property-controls/-/spfx-property-controls-3.8.0.tgz", + "integrity": "sha512-X2DINlpb92E/YkDicThQMrfCuqXdR2wwLwNrFbPiq5O4VHlWYdSBee8NQaNh7yd+q7Q9z7dUcj4P6vHVJ6x+Yg==", + "requires": { + "@microsoft/sp-core-library": "1.14.0", + "@microsoft/sp-lodash-subset": "1.14.0", + "@microsoft/sp-office-ui-fabric-core": "1.14.0", + "@microsoft/sp-property-pane": "1.14.0", + "@microsoft/sp-webpart-base": "1.14.0", + "@monaco-editor/loader": "^1.2.0", + "@pnp/common": "1.3.11", + "@pnp/logging": "1.3.11", + "@pnp/odata": "1.3.11", + "@pnp/sp": "1.3.11", + "@pnp/sp-clientsvc": "1.3.11", + "@pnp/sp-taxonomy": "1.3.11", + "@pnp/telemetry-js": "2.0.0", + "@uifabric/icons": "7.5.17", + "lodash.omit": "4.5.0", + "markdown-to-jsx": "^6.11.4", + "monaco-editor": "^0.32.1", + "office-ui-fabric-react": "7.174.1", + "react": "16.13.1", + "react-ace": "5.8.0", + "react-dom": "16.13.1" + }, + "dependencies": { + "@microsoft/office-ui-fabric-react-bundle": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/office-ui-fabric-react-bundle/-/office-ui-fabric-react-bundle-1.14.0.tgz", + "integrity": "sha512-JhRBHdJrnYjOctHwCH3QBJL2aqD+nrHSK7E2CUMz8mfbUR1xneZRYBwT5EKnpyMT+llx3wuWDkK+7N4zwYOPJg==", + "requires": { + "@microsoft/sp-core-library": "1.14.0", + "@uifabric/icons": "7.6.2", + "office-ui-fabric-react": "7.180.0", + "react": "16.13.1", + "react-dom": "16.13.1", + "tslib": "~1.10.0" + }, + "dependencies": { + "@uifabric/icons": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.6.2.tgz", + "integrity": "sha512-q7jEIwB5Tt2Egw9fqdgNPlBqBQ6hNNMQ3qs5y4S4YETRluB+AQTdKbrbYMsXo3Pm0FsJnRfiDojMzxusGX+MWA==", + "requires": { + "@uifabric/set-version": "^7.0.24", + "@uifabric/styling": "^7.20.0", + "tslib": "^1.10.0" + } + }, + "office-ui-fabric-react": { + "version": "7.180.0", + "resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.180.0.tgz", + "integrity": "sha512-bayPgo2gyJEqYOOwsGT8KZtOj3yWe252PqMFw0Gx/2TKOXweQ/btror1D2SGxins8RogTtwhkmvgTbnWYMn2jw==", + "requires": { + "@fluentui/date-time-utilities": "^7.9.1", + "@fluentui/react-focus": "^7.18.1", + "@fluentui/react-window-provider": "^1.0.2", + "@microsoft/load-themed-styles": "^1.10.26", + "@uifabric/foundation": "^7.10.1", + "@uifabric/icons": "^7.6.2", + "@uifabric/merge-styles": "^7.19.2", + "@uifabric/react-hooks": "^7.14.0", + "@uifabric/set-version": "^7.0.24", + "@uifabric/styling": "^7.20.0", + "@uifabric/utilities": "^7.33.5", + "prop-types": "^15.7.2", + "tslib": "^1.10.0" + } + } + } + }, + "@microsoft/sp-component-base": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-component-base/-/sp-component-base-1.14.0.tgz", + "integrity": "sha512-o9D4iVU9uu1dIxxqK3ScOiZHm7npKaLeyCxckwiMCdJRMsp00RBiyDhAjBykZci/WHs2t14sxEDPvIkQJon+3g==", + "requires": { + "@microsoft/office-ui-fabric-react-bundle": "1.14.0", + "@microsoft/sp-core-library": "1.14.0", + "@microsoft/sp-diagnostics": "1.14.0", + "@microsoft/sp-dynamic-data": "1.14.0", + "@microsoft/sp-http": "1.14.0", + "@microsoft/sp-lodash-subset": "1.14.0", + "@microsoft/sp-module-interfaces": "1.14.0", + "@microsoft/sp-page-context": "1.14.0", + "tslib": "~1.10.0" + } + }, + "@microsoft/sp-core-library": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-core-library/-/sp-core-library-1.14.0.tgz", + "integrity": "sha512-+Do8o0Y6vdCxW+kVZbdWtcU+h+zR9raV9eCPjEBPj4xScB+Y26AE7H8lebAdgNh7rB136JTV+d6/l94FlKKabQ==", + "requires": { + "@microsoft/sp-lodash-subset": "1.14.0", + "@microsoft/sp-module-interfaces": "1.14.0", + "@microsoft/sp-odata-types": "1.14.0", + "tslib": "~1.10.0" + } + }, + "@microsoft/sp-diagnostics": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-diagnostics/-/sp-diagnostics-1.14.0.tgz", + "integrity": "sha512-vuv1JidY7m+uneiYo6c90AIZUub7QCwBqby1gi7x/d9dV7vFfUfdkvZA1on7lvSOx32DVedX/d0W83mvZQRtTA==", + "requires": { + "@microsoft/sp-core-library": "1.14.0", + "@microsoft/sp-lodash-subset": "1.14.0" + } + }, + "@microsoft/sp-dynamic-data": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-dynamic-data/-/sp-dynamic-data-1.14.0.tgz", + "integrity": "sha512-zwFB1G/8HDX7BqIvJqQd7vlTM1d2PfvHEFucZX6fkqoaC05j0dk4Ah0LJFKY767Ke8RD3VfijyakV/gJCkvw6g==", + "requires": { + "@microsoft/sp-core-library": "1.14.0", + "@microsoft/sp-diagnostics": "1.14.0", + "@microsoft/sp-lodash-subset": "1.14.0", + "@microsoft/sp-module-interfaces": "1.14.0", + "tslib": "~1.10.0" + } + }, + "@microsoft/sp-http": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-http/-/sp-http-1.14.0.tgz", + "integrity": "sha512-Md/azXAMSD/DlBBKGuV30y/5lNTdPZ4XKXGc6PcPp8h5mMyqEewdqaCrDhvvDPXZzoNyqYoH1ingdU4W6LRMRA==", + "requires": { + "@microsoft/microsoft-graph-client": "~1.1.0", + "@microsoft/sp-core-library": "1.14.0", + "@microsoft/sp-diagnostics": "1.14.0", + "@types/adal-angular": "1.0.1", + "adal-angular": "1.0.16", + "msal": "1.4.13", + "msalLegacy": "npm:msal@1.4.12", + "tslib": "~1.10.0" + } + }, + "@microsoft/sp-loader": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-loader/-/sp-loader-1.14.0.tgz", + "integrity": "sha512-2Hp8UKaEbIcmcJ7b8HuwzrMYQ3y5z3icVDEST2rzWs+rc+QgINJERF17v8Q35h6d8PSPSevqwwPycAax2T41ZA==", + "requires": { + "@microsoft/office-ui-fabric-react-bundle": "1.14.0", + "@microsoft/sp-core-library": "1.14.0", + "@microsoft/sp-diagnostics": "1.14.0", + "@microsoft/sp-dynamic-data": "1.14.0", + "@microsoft/sp-http": "1.14.0", + "@microsoft/sp-lodash-subset": "1.14.0", + "@microsoft/sp-module-interfaces": "1.14.0", + "@microsoft/sp-odata-types": "1.14.0", + "@microsoft/sp-page-context": "1.14.0", + "@microsoft/sp-polyfills": "1.14.0", + "@rushstack/loader-raw-script": "1.3.207", + "@types/requirejs": "2.1.29", + "office-ui-fabric-react": "7.180.0", + "raw-loader": "~0.5.1", + "react": "16.13.1", + "react-dom": "16.13.1", + "requirejs": "2.3.6", + "tslib": "~1.10.0" + }, + "dependencies": { + "@uifabric/icons": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.7.4.tgz", + "integrity": "sha512-eJa4mqLawuKM8NNpScLD/eQRfXFP9ut3RinKQrNAc9q/zAbj1tYRbJhzZykl1X1WIh4OZOOlJ9YDwGax/RP8sg==", + "requires": { + "@uifabric/set-version": "^7.0.24", + "@uifabric/styling": "^7.21.1", + "@uifabric/utilities": "^7.34.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "@uifabric/styling": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.21.1.tgz", + "integrity": "sha512-5HX5amh8mDRDrP5pdMOYaB/f3KH0m4ZX+cMfU6jj3jREx7jor6ok5J1Vr7zBY+MnUA2soQREJyZvpibT2YeVlg==", + "requires": { + "@fluentui/theme": "^1.7.6", + "@microsoft/load-themed-styles": "^1.10.26", + "@uifabric/merge-styles": "^7.19.2", + "@uifabric/set-version": "^7.0.24", + "@uifabric/utilities": "^7.34.1", + "tslib": "^1.10.0" + } + } + } + }, + "office-ui-fabric-react": { + "version": "7.180.0", + "resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.180.0.tgz", + "integrity": "sha512-bayPgo2gyJEqYOOwsGT8KZtOj3yWe252PqMFw0Gx/2TKOXweQ/btror1D2SGxins8RogTtwhkmvgTbnWYMn2jw==", + "requires": { + "@fluentui/date-time-utilities": "^7.9.1", + "@fluentui/react-focus": "^7.18.1", + "@fluentui/react-window-provider": "^1.0.2", + "@microsoft/load-themed-styles": "^1.10.26", + "@uifabric/foundation": "^7.10.1", + "@uifabric/icons": "^7.6.2", + "@uifabric/merge-styles": "^7.19.2", + "@uifabric/react-hooks": "^7.14.0", + "@uifabric/set-version": "^7.0.24", + "@uifabric/styling": "^7.20.0", + "@uifabric/utilities": "^7.33.5", + "prop-types": "^15.7.2", + "tslib": "^1.10.0" + } + } + } + }, + "@microsoft/sp-lodash-subset": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-lodash-subset/-/sp-lodash-subset-1.14.0.tgz", + "integrity": "sha512-0vY+JuqAsUT9AMEMvMHhcNCtqV1RThxxgMPhzR1lauzKSNkMeFXYwHRsVR6p3BZfaQ2nyeyG5811Wlwchs5SKA==", + "requires": { + "@types/lodash": "4.14.117", + "tslib": "~1.10.0" + } + }, + "@microsoft/sp-module-interfaces": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-module-interfaces/-/sp-module-interfaces-1.14.0.tgz", + "integrity": "sha512-OPQW3vVVADSYTTXUXmBMh3/TAPqiCunPd7Ggfk+fZC82qyI5s7hLCkto9BJ2IkqfxLeOB9/4qxXfQbrrS6wVPg==" + }, + "@microsoft/sp-odata-types": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-odata-types/-/sp-odata-types-1.14.0.tgz", + "integrity": "sha512-SmznMgMaeo0JRq6BBUl+SMPVvJbzECOZtpVowrR5Kz06QIn7pfAL21q1ZwYH9tRJvPDo/awSDXW5qIzt/1jamA==", + "requires": { + "tslib": "~1.10.0" + } + }, + "@microsoft/sp-office-ui-fabric-core": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-office-ui-fabric-core/-/sp-office-ui-fabric-core-1.14.0.tgz", + "integrity": "sha512-FCkyTyM7CiTjXxSDiVLpiqUAR9Pxg+PdTh+KBDvtVBYLeQJI0Zqrwl833SSNl9mixD6doaKwri27LxhCGEN1nQ==", + "requires": { + "office-ui-fabric-core": "9.6.1-fluent2", + "tslib": "~1.10.0" + } + }, + "@microsoft/sp-page-context": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-page-context/-/sp-page-context-1.14.0.tgz", + "integrity": "sha512-WaT3wFY+MoYNjc6Z+cO5uxS7whRG8wzWtNzIGyxi6pLPxSpYyYfmZaDwsf563+hHUldGJpZIwwh0Fy096ysiPg==", + "requires": { + "@microsoft/sp-core-library": "1.14.0", + "@microsoft/sp-diagnostics": "1.14.0", + "@microsoft/sp-dynamic-data": "1.14.0", + "@microsoft/sp-lodash-subset": "1.14.0", + "@microsoft/sp-odata-types": "1.14.0", + "tslib": "~1.10.0" + } + }, + "@microsoft/sp-polyfills": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-polyfills/-/sp-polyfills-1.14.0.tgz", + "integrity": "sha512-TJbYNfsdk1qjODzKQnn5+wcfJm2xBb8uqHNPCxAsoz6+e02HSNkdVM5rAjEq5Sh1Czcn4JIe3AXrz3DJMQnMBA==", + "requires": { + "es6-promise": "4.2.4", + "es6-symbol": "3.1.3", + "tslib": "~1.10.0", + "whatwg-fetch": "2.0.3", + "whatwg-url": "4.7.1" + } + }, + "@microsoft/sp-property-pane": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-property-pane/-/sp-property-pane-1.14.0.tgz", + "integrity": "sha512-1xwpz7RPSQCWnzYNWYPQsFARYp6JlseU2wsXpk02Pmzt9W+Zg0551BUvoCmU9OWeLX0zWjvsLO8sh2zYZkWe/w==", + "requires": { + "@microsoft/office-ui-fabric-react-bundle": "1.14.0", + "@microsoft/sp-component-base": "1.14.0", + "@microsoft/sp-core-library": "1.14.0", + "@microsoft/sp-diagnostics": "1.14.0", + "@microsoft/sp-dynamic-data": "1.14.0", + "@microsoft/sp-lodash-subset": "1.14.0", + "office-ui-fabric-react": "7.180.0", + "react": "16.13.1", + "react-dom": "16.13.1", + "tslib": "~1.10.0" + }, + "dependencies": { + "@uifabric/icons": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.7.4.tgz", + "integrity": "sha512-eJa4mqLawuKM8NNpScLD/eQRfXFP9ut3RinKQrNAc9q/zAbj1tYRbJhzZykl1X1WIh4OZOOlJ9YDwGax/RP8sg==", + "requires": { + "@uifabric/set-version": "^7.0.24", + "@uifabric/styling": "^7.21.1", + "@uifabric/utilities": "^7.34.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "@uifabric/styling": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.21.1.tgz", + "integrity": "sha512-5HX5amh8mDRDrP5pdMOYaB/f3KH0m4ZX+cMfU6jj3jREx7jor6ok5J1Vr7zBY+MnUA2soQREJyZvpibT2YeVlg==", + "requires": { + "@fluentui/theme": "^1.7.6", + "@microsoft/load-themed-styles": "^1.10.26", + "@uifabric/merge-styles": "^7.19.2", + "@uifabric/set-version": "^7.0.24", + "@uifabric/utilities": "^7.34.1", + "tslib": "^1.10.0" + } + } + } + }, + "office-ui-fabric-react": { + "version": "7.180.0", + "resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.180.0.tgz", + "integrity": "sha512-bayPgo2gyJEqYOOwsGT8KZtOj3yWe252PqMFw0Gx/2TKOXweQ/btror1D2SGxins8RogTtwhkmvgTbnWYMn2jw==", + "requires": { + "@fluentui/date-time-utilities": "^7.9.1", + "@fluentui/react-focus": "^7.18.1", + "@fluentui/react-window-provider": "^1.0.2", + "@microsoft/load-themed-styles": "^1.10.26", + "@uifabric/foundation": "^7.10.1", + "@uifabric/icons": "^7.6.2", + "@uifabric/merge-styles": "^7.19.2", + "@uifabric/react-hooks": "^7.14.0", + "@uifabric/set-version": "^7.0.24", + "@uifabric/styling": "^7.20.0", + "@uifabric/utilities": "^7.33.5", + "prop-types": "^15.7.2", + "tslib": "^1.10.0" + } + } + } + }, + "@microsoft/sp-webpart-base": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@microsoft/sp-webpart-base/-/sp-webpart-base-1.14.0.tgz", + "integrity": "sha512-plQ03RxEiSZVDDCc5s12MbnicjdJ2WpgJZwwYTb+y8I4LqiNrdM9V4ls53KZWQbCiYntgm2phHcdHXzeas/DBg==", + "requires": { + "@microsoft/sp-component-base": "1.14.0", + "@microsoft/sp-core-library": "1.14.0", + "@microsoft/sp-diagnostics": "1.14.0", + "@microsoft/sp-dynamic-data": "1.14.0", + "@microsoft/sp-http": "1.14.0", + "@microsoft/sp-loader": "1.14.0", + "@microsoft/sp-lodash-subset": "1.14.0", + "@microsoft/sp-module-interfaces": "1.14.0", + "@microsoft/sp-page-context": "1.14.0", + "@microsoft/sp-property-pane": "1.14.0", + "@microsoft/teams-js": "1.10.0", + "@types/office-js": "1.0.36", + "office-ui-fabric-react": "7.180.0", + "react": "16.13.1", + "react-dom": "16.13.1", + "tslib": "~1.10.0" + }, + "dependencies": { + "@uifabric/icons": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.7.4.tgz", + "integrity": "sha512-eJa4mqLawuKM8NNpScLD/eQRfXFP9ut3RinKQrNAc9q/zAbj1tYRbJhzZykl1X1WIh4OZOOlJ9YDwGax/RP8sg==", + "requires": { + "@uifabric/set-version": "^7.0.24", + "@uifabric/styling": "^7.21.1", + "@uifabric/utilities": "^7.34.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "@uifabric/styling": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.21.1.tgz", + "integrity": "sha512-5HX5amh8mDRDrP5pdMOYaB/f3KH0m4ZX+cMfU6jj3jREx7jor6ok5J1Vr7zBY+MnUA2soQREJyZvpibT2YeVlg==", + "requires": { + "@fluentui/theme": "^1.7.6", + "@microsoft/load-themed-styles": "^1.10.26", + "@uifabric/merge-styles": "^7.19.2", + "@uifabric/set-version": "^7.0.24", + "@uifabric/utilities": "^7.34.1", + "tslib": "^1.10.0" + } + } + } + }, + "office-ui-fabric-react": { + "version": "7.180.0", + "resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.180.0.tgz", + "integrity": "sha512-bayPgo2gyJEqYOOwsGT8KZtOj3yWe252PqMFw0Gx/2TKOXweQ/btror1D2SGxins8RogTtwhkmvgTbnWYMn2jw==", + "requires": { + "@fluentui/date-time-utilities": "^7.9.1", + "@fluentui/react-focus": "^7.18.1", + "@fluentui/react-window-provider": "^1.0.2", + "@microsoft/load-themed-styles": "^1.10.26", + "@uifabric/foundation": "^7.10.1", + "@uifabric/icons": "^7.6.2", + "@uifabric/merge-styles": "^7.19.2", + "@uifabric/react-hooks": "^7.14.0", + "@uifabric/set-version": "^7.0.24", + "@uifabric/styling": "^7.20.0", + "@uifabric/utilities": "^7.33.5", + "prop-types": "^15.7.2", + "tslib": "^1.10.0" + } + } + } + }, + "@rushstack/loader-raw-script": { + "version": "1.3.207", + "resolved": "https://registry.npmjs.org/@rushstack/loader-raw-script/-/loader-raw-script-1.3.207.tgz", + "integrity": "sha512-sOF21pgIKhXREKepRMFMCi0UmChVj2LtjhUP38W5EwJG8sTtv8dOsZ3qT2lW7s+n6TzoPXE8NvY0/dK40VKhug==", + "requires": { + "loader-utils": "~1.1.0" + } + }, + "@uifabric/icons": { + "version": "7.5.17", + "resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.5.17.tgz", + "integrity": "sha512-2S1kse0gtseTuV2r59iWukLxxoOJ6GgP2Yhxt9oxzaP9QubpYdxCUepvJmfPQQvvy4GELdykDUWQ6/hbzliJyw==", + "requires": { + "@uifabric/set-version": "^7.0.23", + "@uifabric/styling": "^7.16.18", + "tslib": "^1.10.0" + } + }, + "es6-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" + }, + "office-ui-fabric-react": { + "version": "7.174.1", + "resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.174.1.tgz", + "integrity": "sha512-zRUpUqZtVncvb+Tt+5SVNEcI3MfpwTLU+v2u7ZdF9ukPbD+UBKJSkIbydyO0P2S5jVizgdqioSOarfUA70ICvw==", + "requires": { + "@fluentui/date-time-utilities": "^7.9.1", + "@fluentui/react-focus": "^7.17.6", + "@fluentui/react-window-provider": "^1.0.2", + "@microsoft/load-themed-styles": "^1.10.26", + "@uifabric/foundation": "^7.9.26", + "@uifabric/icons": "^7.5.23", + "@uifabric/merge-styles": "^7.19.2", + "@uifabric/react-hooks": "^7.14.0", + "@uifabric/set-version": "^7.0.24", + "@uifabric/styling": "^7.19.0", + "@uifabric/utilities": "^7.33.5", + "prop-types": "^15.7.2", + "tslib": "^1.10.0" + }, + "dependencies": { + "@uifabric/icons": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.7.4.tgz", + "integrity": "sha512-eJa4mqLawuKM8NNpScLD/eQRfXFP9ut3RinKQrNAc9q/zAbj1tYRbJhzZykl1X1WIh4OZOOlJ9YDwGax/RP8sg==", + "requires": { + "@uifabric/set-version": "^7.0.24", + "@uifabric/styling": "^7.21.1", + "@uifabric/utilities": "^7.34.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "@uifabric/styling": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.21.1.tgz", + "integrity": "sha512-5HX5amh8mDRDrP5pdMOYaB/f3KH0m4ZX+cMfU6jj3jREx7jor6ok5J1Vr7zBY+MnUA2soQREJyZvpibT2YeVlg==", + "requires": { + "@fluentui/theme": "^1.7.6", + "@microsoft/load-themed-styles": "^1.10.26", + "@uifabric/merge-styles": "^7.19.2", + "@uifabric/set-version": "^7.0.24", + "@uifabric/utilities": "^7.34.1", + "tslib": "^1.10.0" + } + } + } + } + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + }, + "whatwg-fetch": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", + "integrity": "sha512-SA2KdOXATOroD3EBUYvcdugsusXS5YiQFqwskSbsp5b1gK8HpNi/YP0jcy/BDpdllp305HMnrsVf9K7Be9GiEQ==" + } + } + }, + "@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": { + "whatwg-fetch": "2.0.4" + }, + "dependencies": { + "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==" + } + } + }, "@pnpm/error": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@pnpm/error/-/error-1.4.0.tgz", @@ -5760,6 +6363,11 @@ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true }, + "brace": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/brace/-/brace-0.11.1.tgz", + "integrity": "sha512-Fc8Ne62jJlKHiG/ajlonC4Sd66Pq68fFwK4ihJGNZpGqboc324SQk+lRvMzpPRuJOmfrJefdG8/7JdWX4bzJ2Q==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -14136,6 +14744,11 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==" + }, "lodash.restparam": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", @@ -14290,6 +14903,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://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", @@ -14721,6 +15343,11 @@ "minimist": "^1.2.6" } }, + "monaco-editor": { + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.32.1.tgz", + "integrity": "sha512-LUt2wsUvQmEi2tfTOK+tjAPvt7eQ+K5C4rZPr6SeuyzjAuAHrIvlUloTcOiGjZW3fn3a/jFQCONrEJbNOaCqbA==" + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -17115,6 +17742,17 @@ "prop-types": "^15.6.2" } }, + "react-ace": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/react-ace/-/react-ace-5.8.0.tgz", + "integrity": "sha512-50OXFDqL9C5t4/rxuyTZyEfsaRfH9RlqKqQ86OPVhNGxlGj2U78yL6GHqbcxYd/PZXbqBvsFhYclUx9zugtH7Q==", + "requires": { + "brace": "^0.11.0", + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.1.1", + "prop-types": "^15.5.8" + } + }, "react-dom": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz", @@ -18901,6 +19539,11 @@ } } }, + "state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -20013,8 +20656,7 @@ "unquote": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/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-graph-profile-awards/package.json b/samples/react-graph-profile-awards/package.json index a14d43ea1..85bce7b02 100644 --- a/samples/react-graph-profile-awards/package.json +++ b/samples/react-graph-profile-awards/package.json @@ -9,15 +9,16 @@ "test": "gulp test" }, "dependencies": { - "tslib": "1.13.0", - "react": "16.13.1", - "react-dom": "16.13.1", - "office-ui-fabric-react": "7.181.1", "@microsoft/sp-core-library": "1.15.0-beta.1", + "@microsoft/sp-lodash-subset": "1.15.0-beta.1", + "@microsoft/sp-office-ui-fabric-core": "1.15.0-beta.1", "@microsoft/sp-property-pane": "1.15.0-beta.1", "@microsoft/sp-webpart-base": "1.15.0-beta.1", - "@microsoft/sp-lodash-subset": "1.15.0-beta.1", - "@microsoft/sp-office-ui-fabric-core": "1.15.0-beta.1" + "@pnp/spfx-property-controls": "3.8.0", + "office-ui-fabric-react": "7.181.1", + "react": "16.13.1", + "react-dom": "16.13.1", + "tslib": "1.13.0" }, "devDependencies": { "@microsoft/rush-stack-compiler-3.9": "0.4.47", diff --git a/samples/react-graph-profile-awards/src/models/IAward.ts b/samples/react-graph-profile-awards/src/models/IAward.ts index 39bda3cc7..d654ba492 100644 --- a/samples/react-graph-profile-awards/src/models/IAward.ts +++ b/samples/react-graph-profile-awards/src/models/IAward.ts @@ -5,7 +5,7 @@ export interface IAward { displayName: string; allowedAudiences: allowedAudiences; description: string; - issuedDate: Date; + issuedDate: string; issuingAuthority: string; thumbnailUrl: string; webUrl: string; diff --git a/samples/react-graph-profile-awards/src/services/AwardsService.ts b/samples/react-graph-profile-awards/src/services/AwardsService.ts index 831c7f0fc..317761638 100644 --- a/samples/react-graph-profile-awards/src/services/AwardsService.ts +++ b/samples/react-graph-profile-awards/src/services/AwardsService.ts @@ -1,14 +1,14 @@ import { ServiceKey, ServiceScope } from "@microsoft/sp-core-library"; import { IAward } from "../models/IAward"; -import { MSGraphClientFactory, HttpClientResponse } from "@microsoft/sp-http"; +import { MSGraphClientFactory } from "@microsoft/sp-http"; import { IListAwardsResponse } from "../models/IListAwardsResponse"; export interface IAwardsService { - getMyAwards(): Promise; + getMyAwards(userId: string): Promise; } export default class AwardsService implements IAwardsService { - private readonly GraphMyAwardsEndpoint: string = 'https://graph.microsoft.com/beta/me/profile/awards'; + private readonly GraphMyAwardsEndpoint: string = 'https://graph.microsoft.com/beta/users/{userId}/profile/awards'; private _msGraphClientFactory: MSGraphClientFactory; constructor(serviceScope:ServiceScope) { @@ -17,11 +17,11 @@ export default class AwardsService implements IAwardsService { }); } - public async getMyAwards(): Promise { + public async getMyAwards(userId: string): Promise { const msGraphClient = await this._msGraphClientFactory.getClient("3"); - + const endpoint = this.GraphMyAwardsEndpoint.replace('{userId}', userId); // It works with ObjectId and LoginName const listAwardsResponse: IListAwardsResponse = await msGraphClient - .api(this.GraphMyAwardsEndpoint) + .api(endpoint) .orderby('issuedDate desc') .get(); @@ -29,4 +29,4 @@ export default class AwardsService implements IAwardsService { } } -export const AwardsServiceKey = ServiceKey.create("atlas:featuresService", AwardsService); \ No newline at end of file +export const AwardsServiceKey = ServiceKey.create("pnp:awardsService", AwardsService); \ No newline at end of file diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/MyAwardsWebPart.manifest.json b/samples/react-graph-profile-awards/src/webparts/myAwards/MyAwardsWebPart.manifest.json index 5665cac32..a5990ff75 100644 --- a/samples/react-graph-profile-awards/src/webparts/myAwards/MyAwardsWebPart.manifest.json +++ b/samples/react-graph-profile-awards/src/webparts/myAwards/MyAwardsWebPart.manifest.json @@ -3,26 +3,20 @@ "id": "a62fd5a8-90e0-4712-8569-57c0b11d9f89", "alias": "MyAwardsWebPart", "componentType": "WebPart", - - // The "*" signifies that the version should be taken from the package.json "version": "*", "manifestVersion": 2, - - // If true, the component can only be installed on sites where Custom Script is allowed. - // 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, "supportedHosts": ["SharePointWebPart", "TeamsPersonalApp", "TeamsTab", "SharePointFullPage"], "supportsThemeVariants": true, - "preconfiguredEntries": [{ - "groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other + "groupId": "5c03119e-3074-46fd-976b-c60198311f70", "group": { "default": "Other" }, - "title": { "default": "MyAwards" }, - "description": { "default": "MyAwards description" }, + "title": { "default": "Awards" }, + "description": { "default": "Show user profile awards. It uses Graph beta endpoint to get the profile awards of the selected user." }, "officeFabricIconFontName": "Page", "properties": { - "description": "MyAwards" + "layoutType": "Card", + "selectedUserOrigin": "CurrentUser" } }] } diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/MyAwardsWebPart.ts b/samples/react-graph-profile-awards/src/webparts/myAwards/MyAwardsWebPart.ts index 95dd78e87..484b6845b 100644 --- a/samples/react-graph-profile-awards/src/webparts/myAwards/MyAwardsWebPart.ts +++ b/samples/react-graph-profile-awards/src/webparts/myAwards/MyAwardsWebPart.ts @@ -1,34 +1,55 @@ -import * as React from 'react'; -import * as ReactDom from 'react-dom'; -import { Version } from '@microsoft/sp-core-library'; +import * as React from "react"; +import * as ReactDom from "react-dom"; +import { Version } from "@microsoft/sp-core-library"; import { IPropertyPaneConfiguration, - PropertyPaneTextField -} from '@microsoft/sp-property-pane'; -import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base'; -import { IReadonlyTheme } from '@microsoft/sp-component-base'; + PropertyPaneChoiceGroup, + IPropertyPaneField, + PropertyPaneLabel, + PropertyPaneDynamicField, +} from "@microsoft/sp-property-pane"; +import { + BaseClientSideWebPart, + IWebPartPropertiesMetadata, +} from "@microsoft/sp-webpart-base"; +import { IReadonlyTheme } from "@microsoft/sp-component-base"; -import * as strings from 'MyAwardsWebPartStrings'; -import MyAwards from './components/MyAwards'; -import { IMyAwardsProps } from './components/IMyAwardsProps'; -import { AwardsServiceKey, IAwardsService } from '../../services/AwardsService'; +import { + PropertyFieldPeoplePicker, + PrincipalType, + IPropertyFieldGroupOrPerson, +} from "@pnp/spfx-property-controls/lib/PropertyFieldPeoplePicker"; + +import { DynamicProperty } from "@microsoft/sp-component-base"; + +import * as strings from "MyAwardsWebPartStrings"; +import AwardsContainer from "./components/AwardsContainer"; +import { IAwardsContainerProps, LayoutType } from "./components/IAwardsContainerProps"; +import { AwardsServiceKey, IAwardsService } from "../../services/AwardsService"; export interface IMyAwardsWebPartProps { - description: string; + selectedUserOrigin: string; + people: IPropertyFieldGroupOrPerson[]; + selectedUserId: string; + selectedUserInPageEnvironment: DynamicProperty; + layoutType: LayoutType; } export default class MyAwardsWebPart extends BaseClientSideWebPart { - private _isDarkTheme: boolean = false; private _awardsService: IAwardsService; public render(): void { - const element: React.ReactElement = React.createElement( - MyAwards, + this._getSelectedUser(); + + const element: React.ReactElement = React.createElement( + AwardsContainer, { isDarkTheme: this._isDarkTheme, hasTeamsContext: !!this.context.sdks.microsoftTeams, - awardsService: this._awardsService + awardsService: this._awardsService, + userId: this.properties.selectedUserId, + layoutType: this.properties.layoutType, } ); @@ -36,13 +57,14 @@ export default class MyAwardsWebPart extends BaseClientSideWebPart { - return super.onInit() - .then(_ => { + return super + .onInit() + .then((_) => { let webpartScope = this.context.serviceScope.startNewChild(); webpartScope.finish(); return webpartScope; }) - .then(serviceScope => { + .then((serviceScope) => { this._awardsService = serviceScope.consume(AwardsServiceKey); }); } @@ -53,13 +75,13 @@ export default class MyAwardsWebPart extends BaseClientSideWebPart; + switch (this.properties.selectedUserOrigin) { + case "PeoplePicker": + field = PropertyFieldPeoplePicker("people", { + label: "Select a user", + initialData: this.properties.people, + allowDuplicate: false, + principalType: [PrincipalType.Users], + onPropertyChange: this._onPeoplePickerFieldChanged, + context: this.context as any, + properties: this.properties, + onGetErrorMessage: null, + deferredValidationTime: 0, + key: "peopleFieldId", + multiSelect: false, + }); + break; + case "DynamicData": + field = PropertyPaneDynamicField("selectedUserInPageEnvironment", { + label: "Select user value from page environment", + }); + break; + default: + field = PropertyPaneLabel("me", { + text: `Your user ${this.context.pageContext.user.displayName} will be used`, + }); + break; + } + return { pages: [ { - header: { - description: strings.PropertyPaneDescription - }, groups: [ { groupName: strings.BasicGroupName, groupFields: [ - PropertyPaneTextField('description', { - label: strings.DescriptionFieldLabel - }) - ] - } - ] - } - ] + PropertyPaneChoiceGroup("selectedUserOrigin", { + label: "Select user from:", + options: [ + { + iconProps: { + officeFabricIconFontName: "People", + }, + imageSize: { + width: 200, + height: 100, + }, + key: "PeoplePicker", + text: "People picker", + }, + { + iconProps: { + officeFabricIconFontName: "Link", + }, + imageSize: { + width: 200, + height: 100, + }, + key: "DynamicData", + text: "Dynamic Data", + }, + { + iconProps: { + officeFabricIconFontName: "NUIFace", + }, + imageSize: { + width: 200, + height: 100, + }, + key: "CurrentUser", + text: "Me", + }, + ], + }), + field, + ], + }, + { + groupName: "Layout", + groupFields: [ + PropertyPaneChoiceGroup("layoutType", { + label: "Select a Layout:", + options: [ + { + iconProps: { + officeFabricIconFontName: "BusinessCard", + }, + imageSize: { + width: 200, + height: 100, + }, + key: "Card", + text: "Card", + }, + { + iconProps: { + officeFabricIconFontName: "BulletedList", + }, + imageSize: { + width: 200, + height: 100, + }, + key: "List", + text: "List", + }, + ], + }), + ], + }, + ], + }, + ], }; } + + private _onPeoplePickerFieldChanged( + propertyPath: string, + oldValue: any, + newValue: any + ): void { + this.properties.selectedUserId = newValue[0].login; + } + + private _getSelectedUser(): void { + let userId: string = this.context.pageContext.user.loginName; + switch (this.properties.selectedUserOrigin) { + case "PeoplePicker": + if (!this.properties.people) break; + userId = this.properties.people[0].login; + break; + case "DynamicData": + const userIdInPageContext: string = this.properties.selectedUserInPageEnvironment.tryGetValue(); + if (userIdInPageContext && typeof(userIdInPageContext) === 'string') userId = userIdInPageContext; // For some reason, when you select "Page environment/QueryString" it returns an object here (should be a string) (issues related: https://github.com/SharePoint/sp-dev-docs/issues/5947 and https://github.com/microsoft-search/pnp-modern-search/issues/325) + break; + } + + this.properties.selectedUserId = userId; + } } diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/components/Award.tsx b/samples/react-graph-profile-awards/src/webparts/myAwards/components/Award.tsx deleted file mode 100644 index 2f1155c8b..000000000 --- a/samples/react-graph-profile-awards/src/webparts/myAwards/components/Award.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import * as React from "react"; -import styles from "./MyAwards.module.scss"; -import { IAward } from "../../../models/IAward"; - -export interface IAwardProps { - award: IAward; -} - -export default class MyAwards extends React.Component { - public render(): React.ReactElement { - const { - displayName, - description, - issuedDate, - issuingAuthority, - thumbnailUrl, - webUrl, - } = this.props.award; - - return ( -
-
-
-
{issuingAuthority}
- Award - - View details - -
-
-
{issuedDate}
-

{displayName}

-

{description}

-
-
-
- ); - } -} diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/components/AwardCard.tsx b/samples/react-graph-profile-awards/src/webparts/myAwards/components/AwardCard.tsx new file mode 100644 index 000000000..df2301a1d --- /dev/null +++ b/samples/react-graph-profile-awards/src/webparts/myAwards/components/AwardCard.tsx @@ -0,0 +1,42 @@ +import * as React from "react"; +import { IAwardBaseProps } from "./IAwardBaseProps"; +import styles from "./Awards.module.scss"; + +export default class AwardCard extends React.Component { + constructor(props: IAwardBaseProps) { + super(props); + } + + public render(): React.ReactElement { + const { + id, + displayName, + description, + issuedDate, + issuingAuthority, + thumbnailUrl, + webUrl, + } = this.props.award; + + return ( +
+
{issuingAuthority}
+
+ {displayName} +
+
{displayName}
+
+

{description}

+
+
+
{issuedDate}
+ +
+
+ ); + } +} diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/components/AwardListItem.tsx b/samples/react-graph-profile-awards/src/webparts/myAwards/components/AwardListItem.tsx new file mode 100644 index 000000000..da281fdc1 --- /dev/null +++ b/samples/react-graph-profile-awards/src/webparts/myAwards/components/AwardListItem.tsx @@ -0,0 +1,45 @@ +import * as React from "react"; +import { IAwardBaseProps } from "./IAwardBaseProps"; +import styles from './Awards.module.scss'; + +export default class AwardListItem extends React.Component< + IAwardBaseProps, + {} +> { + constructor(props: IAwardBaseProps) { + super(props); + } + + public render(): React.ReactElement { + const { + id, + displayName, + description, + issuedDate, + issuingAuthority, + thumbnailUrl, + webUrl, + } = this.props.award; + + return ( +
+
+ {displayName} +
+
+
{issuingAuthority}
+
{displayName}
+

{description}

+
+
{issuedDate}
+ +
+
+
+ ); + } +} diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/components/Awards.module.scss b/samples/react-graph-profile-awards/src/webparts/myAwards/components/Awards.module.scss new file mode 100644 index 000000000..d17106333 --- /dev/null +++ b/samples/react-graph-profile-awards/src/webparts/myAwards/components/Awards.module.scss @@ -0,0 +1,103 @@ +@import "~office-ui-fabric-react/dist/sass/References.scss"; + +p { + font-size: 12px; + color: #3B3838; +} + +.App { + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; +} + +.awards_container { + padding: 10px; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); + grid-auto-rows: auto; + grid-gap: 1rem; +} + +.award_card { + border-radius: 8px; + padding: 0.5rem; + background-color: #5CC8FF; + display: grid; +} + +.award_title { + font-size: 18px; + font-weight: 700; + color: white; +} + +.award_card img { + max-width: 150px; + max-height: 150px; +} + +.award_issuedby { + font-size: 14px; + text-align: center; + color: white; +} + +.award_thumbnail { + text-align: center; + padding-top: 10px; + padding-bottom: 10px; +} + +.award_footer { + display: grid; + grid-template-columns: 1fr 1fr; + align-self: end; + font-size: 12px; +} + +.award_footer a { + color: black; + text-decoration: none; + font-weight: 600; +} + +.award_when { + color: white; + font-weight: 600; +} + +.award_details { + text-align: end; +} + +.awards_list_container { + padding: 10px; + display: grid; + grid-template-rows: 1fr; + grid-auto-columns: auto; + grid-gap: 1rem; +} + +.award_list_item { + border-radius: 8px; + padding: 0.5rem; + background-color: #5CC8FF; + max-width: 600px; + display: grid; + grid-template-columns: 1fr 3fr; +} + +.award_list_item img { + max-width: 100px; + max-height: 100px; +} + +.award_list_item_content .award_issuedby { + text-align: left; +} + +.award_list_item_img { + text-align: center; + display: flex; + justify-content: center; + align-items: center; +} \ No newline at end of file diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/components/AwardsContainer.tsx b/samples/react-graph-profile-awards/src/webparts/myAwards/components/AwardsContainer.tsx new file mode 100644 index 000000000..5d37eb1b2 --- /dev/null +++ b/samples/react-graph-profile-awards/src/webparts/myAwards/components/AwardsContainer.tsx @@ -0,0 +1,62 @@ +import * as React from 'react'; +import styles from './Awards.module.scss'; +import { IAwardsContainerProps } from './IAwardsContainerProps'; +import { IAwardsContainerState } from './IAwardsContainerState'; +import { IAwardsService } from '../../../services/AwardsService'; +import AwardListItem from './AwardListItem'; +import AwardCard from './AwardCard'; + +export default class AwardsContainer extends React.Component { + + private _service: IAwardsService; + + constructor(props: IAwardsContainerProps) { + super(props); + this.state = { + awards: [] + }; + this._service = this.props.awardsService; + } + + public componentDidMount(): void { + this._service.getMyAwards(this.props.userId).then(awards => { + this.setState({ + awards: awards + }); + }); + } + + public componentDidUpdate(prevProps: IAwardsContainerProps): void { + if (this.props.userId !== prevProps.userId) { + this._service.getMyAwards(this.props.userId).then(awards => { + this.setState({ + awards: awards + }); + }); + } + } + + public render(): React.ReactElement { + + if(this.state.awards.length == 0) { + return (
User {this.props.userId} has no awards.
); + } + + const { + hasTeamsContext, + } = this.props; + + let awards: JSX.Element[] = []; + let containerClassName = styles.awards_container; + if (this.props.layoutType == 'List') { + awards = this.state.awards.map(award => ); + containerClassName = styles.awards_list_container; + } else { + awards = this.state.awards.map(award => ); + } + + return (
+ {awards} +
); + } +} \ No newline at end of file diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/components/IAwardBaseProps.ts b/samples/react-graph-profile-awards/src/webparts/myAwards/components/IAwardBaseProps.ts new file mode 100644 index 000000000..a297ebd28 --- /dev/null +++ b/samples/react-graph-profile-awards/src/webparts/myAwards/components/IAwardBaseProps.ts @@ -0,0 +1,5 @@ +import { IAward } from "../../../models/IAward"; + +export interface IAwardBaseProps { + award: IAward; +} \ No newline at end of file diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/components/IMyAwardsProps.ts b/samples/react-graph-profile-awards/src/webparts/myAwards/components/IAwardsContainerProps.ts similarity index 54% rename from samples/react-graph-profile-awards/src/webparts/myAwards/components/IMyAwardsProps.ts rename to samples/react-graph-profile-awards/src/webparts/myAwards/components/IAwardsContainerProps.ts index 7b67624f2..ca992c16a 100644 --- a/samples/react-graph-profile-awards/src/webparts/myAwards/components/IMyAwardsProps.ts +++ b/samples/react-graph-profile-awards/src/webparts/myAwards/components/IAwardsContainerProps.ts @@ -1,7 +1,11 @@ import { IAwardsService } from "../../../services/AwardsService"; -export interface IMyAwardsProps { +export type LayoutType = "Card" | "List"; + +export interface IAwardsContainerProps { isDarkTheme: boolean; hasTeamsContext: boolean; awardsService: IAwardsService; + userId: string; + layoutType: LayoutType; } diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/components/IMyAwardsState.ts b/samples/react-graph-profile-awards/src/webparts/myAwards/components/IAwardsContainerState.ts similarity index 64% rename from samples/react-graph-profile-awards/src/webparts/myAwards/components/IMyAwardsState.ts rename to samples/react-graph-profile-awards/src/webparts/myAwards/components/IAwardsContainerState.ts index eb40b59a4..669e67ebb 100644 --- a/samples/react-graph-profile-awards/src/webparts/myAwards/components/IMyAwardsState.ts +++ b/samples/react-graph-profile-awards/src/webparts/myAwards/components/IAwardsContainerState.ts @@ -1,5 +1,5 @@ import { IAward } from "../../../models/IAward"; -export interface IMyAwardsState { +export interface IAwardsContainerState { awards: IAward[]; } \ No newline at end of file diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/components/MyAwards.module.scss b/samples/react-graph-profile-awards/src/webparts/myAwards/components/MyAwards.module.scss deleted file mode 100644 index 9dd6fa73c..000000000 --- a/samples/react-graph-profile-awards/src/webparts/myAwards/components/MyAwards.module.scss +++ /dev/null @@ -1,76 +0,0 @@ -@import "~office-ui-fabric-react/dist/sass/References.scss"; - -.myAwards { - overflow: hidden; - padding: 1em; - color: "[theme:bodyText, default: #323130]"; - color: var(--bodyText); - &.teams { - font-family: $ms-font-family-fallbacks; - } -} - -.myAwards ul { - list-style-type: none; /* Remove bullets */ - padding: 0; /* Remove padding */ - margin: 0; /* Remove margins */ -} - -.welcome { - text-align: center; -} - -.welcomeImage { - width: 100%; - max-width: 420px; -} - -.award img { - border-radius: 50%; - width: 150px; - height: 150px; -} - -.award { - background-color: #fff; - border-radius: 10px; - box-shadow: 0 10px 10px rgba(0, 0, 0, 0.2); - display: flex; - max-width: 100%; - margin: 20px; - overflow: hidden; -} - -.award h6 { - opacity: 0.6; - margin: 0; - letter-spacing: 1px; - text-transform: uppercase; -} - -.award h2 { - letter-spacing: 1px; - margin: 10px 0; -} - -.awardPreview { - background-color: #2a265f; - color: #fff; - padding: 30px; - max-width: 250px; -} - -.awardPreview a { - color: #fff; - display: inline-block; - font-size: 12px; - opacity: 0.6; - margin-top: 30px; - text-decoration: none; -} - -.awardInfo { - padding: 30px; - position: relative; - width: 100%; -} diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/components/MyAwards.tsx b/samples/react-graph-profile-awards/src/webparts/myAwards/components/MyAwards.tsx deleted file mode 100644 index e0e95cfe4..000000000 --- a/samples/react-graph-profile-awards/src/webparts/myAwards/components/MyAwards.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import * as React from 'react'; -import styles from './MyAwards.module.scss'; -import { IMyAwardsProps } from './IMyAwardsProps'; -import { IMyAwardsState } from './IMyAwardsState'; -import { IAwardsService } from '../../../services/AwardsService'; -import Award from './Award'; - -export default class MyAwards extends React.Component { - - private _service: IAwardsService; - - constructor(props: IMyAwardsProps) { - super(props); - this.state = { - awards: [] - }; - this._service = this.props.awardsService; - } - - public componentDidMount(): void { - this._service.getMyAwards().then(awards => { - this.setState({ - awards: awards - }); - }); - } - - public render(): React.ReactElement { - const { - hasTeamsContext, - } = this.props; - - const awards =
    {this.state.awards.map(t =>
  • )}
; - - return ( -
-
-

My Awards

- {awards} -
-
- ); - } -} diff --git a/samples/react-graph-profile-awards/src/webparts/myAwards/loc/en-us.js b/samples/react-graph-profile-awards/src/webparts/myAwards/loc/en-us.js index 7efbd643f..77d4406af 100644 --- a/samples/react-graph-profile-awards/src/webparts/myAwards/loc/en-us.js +++ b/samples/react-graph-profile-awards/src/webparts/myAwards/loc/en-us.js @@ -1,7 +1,7 @@ define([], function() { return { "PropertyPaneDescription": "Description", - "BasicGroupName": "Group Name", + "BasicGroupName": "Data Source", "DescriptionFieldLabel": "Description Field", "AppLocalEnvironmentSharePoint": "The app is running on your local environment as SharePoint web part", "AppLocalEnvironmentTeams": "The app is running on your local environment as Microsoft Teams app",