Allows user selection from different origins, and has 2 different rendering layouts.

This commit is contained in:
Luis Mañez 2022-08-06 08:59:34 +02:00
parent 62221196e7
commit 1479ae724e
21 changed files with 1129 additions and 235 deletions

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

View File

@ -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"
}
}
}

View File

@ -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",

View File

@ -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",

View File

@ -5,7 +5,7 @@ export interface IAward {
displayName: string;
allowedAudiences: allowedAudiences;
description: string;
issuedDate: Date;
issuedDate: string;
issuingAuthority: string;
thumbnailUrl: string;
webUrl: string;

View File

@ -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<IAward[]>;
getMyAwards(userId: string): Promise<IAward[]>;
}
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<IAward[]> {
public async getMyAwards(userId: string): Promise<IAward[]> {
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<IAwardsService>("atlas:featuresService", AwardsService);
export const AwardsServiceKey = ServiceKey.create<IAwardsService>("pnp:awardsService", AwardsService);

View File

@ -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"
}
}]
}

View File

@ -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<string>;
layoutType: LayoutType;
}
export default class MyAwardsWebPart extends BaseClientSideWebPart<IMyAwardsWebPartProps> {
private _isDarkTheme: boolean = false;
private _awardsService: IAwardsService;
public render(): void {
const element: React.ReactElement<IMyAwardsProps> = React.createElement(
MyAwards,
this._getSelectedUser();
const element: React.ReactElement<IAwardsContainerProps> = 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<IMyAwardsWebP
}
protected onInit(): Promise<void> {
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<IMyAwardsWebP
}
this._isDarkTheme = !!currentTheme.isInverted;
const {
semanticColors
} = currentTheme;
this.domElement.style.setProperty('--bodyText', semanticColors.bodyText);
this.domElement.style.setProperty('--link', semanticColors.link);
this.domElement.style.setProperty('--linkHovered', semanticColors.linkHovered);
const { semanticColors } = currentTheme;
this.domElement.style.setProperty("--bodyText", semanticColors.bodyText);
this.domElement.style.setProperty("--link", semanticColors.link);
this.domElement.style.setProperty(
"--linkHovered",
semanticColors.linkHovered
);
}
protected onDispose(): void {
@ -67,28 +89,158 @@ export default class MyAwardsWebPart extends BaseClientSideWebPart<IMyAwardsWebP
}
protected get dataVersion(): Version {
return Version.parse('1.0');
return Version.parse("1.0");
}
protected get propertiesMetadata(): IWebPartPropertiesMetadata {
return {
selectedUserInPageEnvironment: {
dynamicPropertyType: "string",
},
};
}
// protected get disableReactivePropertyChanges(): boolean {
// return true;
// }
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
let field: IPropertyPaneField<any>;
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;
}
}

View File

@ -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<IAwardProps, {}> {
public render(): React.ReactElement<IAwardProps> {
const {
displayName,
description,
issuedDate,
issuingAuthority,
thumbnailUrl,
webUrl,
} = this.props.award;
return (
<div>
<div className={styles.award}>
<div className={styles.awardPreview}>
<h6>{issuingAuthority}</h6>
<img
src={thumbnailUrl}
alt="Award"
/>
<a href={webUrl}>
View details
</a>
</div>
<div className={styles.awardInfo}>
<h6>{issuedDate}</h6>
<h2>{displayName}</h2>
<p>{description}</p>
</div>
</div>
</div>
);
}
}

View File

@ -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<IAwardBaseProps, {}> {
constructor(props: IAwardBaseProps) {
super(props);
}
public render(): React.ReactElement<IAwardBaseProps> {
const {
id,
displayName,
description,
issuedDate,
issuingAuthority,
thumbnailUrl,
webUrl,
} = this.props.award;
return (
<div className={styles.award_card} id={id}>
<div className={styles.award_issuedby}>{issuingAuthority}</div>
<div className={styles.award_thumbnail}>
<img src={thumbnailUrl} alt={displayName} />
</div>
<div className={styles.award_title}>{displayName}</div>
<div>
<p>{description}</p>
</div>
<div className={styles.award_footer}>
<div className={styles.award_when}>{issuedDate}</div>
<div className={styles.award_details}>
<a href={webUrl} target="_blank">
View details
</a>
</div>
</div>
</div>
);
}
}

View File

@ -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<IAwardBaseProps> {
const {
id,
displayName,
description,
issuedDate,
issuingAuthority,
thumbnailUrl,
webUrl,
} = this.props.award;
return (
<div className={styles.award_list_item} id={id}>
<div className={styles.award_list_item_img}>
<img src={thumbnailUrl} alt={displayName} />
</div>
<div className={styles.award_list_item_content}>
<div className={styles.award_issuedby}>{issuingAuthority}</div>
<div className={styles.award_title}>{displayName}</div>
<div><p>{description}</p></div>
<div className={styles.award_footer}>
<div className={styles.award_when}>{issuedDate}</div>
<div className={styles.award_details}>
<a href={webUrl} target="_blank">
View details
</a>
</div>
</div>
</div>
</div>
);
}
}

View File

@ -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;
}

View File

@ -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<IAwardsContainerProps, IAwardsContainerState> {
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<IAwardsContainerProps> {
if(this.state.awards.length == 0) {
return (<div>User {this.props.userId} has no awards.</div>);
}
const {
hasTeamsContext,
} = this.props;
let awards: JSX.Element[] = [];
let containerClassName = styles.awards_container;
if (this.props.layoutType == 'List') {
awards = this.state.awards.map(award => <AwardListItem award={award} />);
containerClassName = styles.awards_list_container;
} else {
awards = this.state.awards.map(award => <AwardCard award={award} />);
}
return (<div className={containerClassName}>
{awards}
</div>);
}
}

View File

@ -0,0 +1,5 @@
import { IAward } from "../../../models/IAward";
export interface IAwardBaseProps {
award: IAward;
}

View File

@ -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;
}

View File

@ -1,5 +1,5 @@
import { IAward } from "../../../models/IAward";
export interface IMyAwardsState {
export interface IAwardsContainerState {
awards: IAward[];
}

View File

@ -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%;
}

View File

@ -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<IMyAwardsProps, IMyAwardsState> {
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<IMyAwardsProps> {
const {
hasTeamsContext,
} = this.props;
const awards = <ul>{this.state.awards.map(t => <li key={t.id}><Award award={t} /></li>)}</ul>;
return (
<section className={`${styles.myAwards} ${hasTeamsContext ? styles.teams : ''}`}>
<div>
<h3>My Awards</h3>
{awards}
</div>
</section>
);
}
}

View File

@ -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",