Updated sample.json and readme.md

This commit is contained in:
Hugo Bernier 2021-10-31 01:31:51 -04:00
parent 2f49498b14
commit 935b0e9517
8 changed files with 289 additions and 59 deletions

View File

@ -1,16 +1,16 @@
# react-emoji-ratings
# Emoji Ratings
## Summary
This is sample web part which can be used to take emoji based reaction or feedback for particular news/article/posts.
We all know every organizations would be using SharePoint news features for company's internal communications from HR to IT updates and some time annoucements. News created in SharePoint are created as Pages in library. Idea behind this webpart is to take employee/user's feedback as emoji reactions on particular news. This webpart can also be used on wiki articles or blog posts to take similar reactions. Webpart uses concept of 1 to 5 star based rating system(configurable), you can decide low to high based on your preference.
We all know every organizations would be using SharePoint news features for company's internal communications from HR to IT updates and some time annoucements. News created in SharePoint are created as Pages in library. Idea behind this web part is to take employee/user's feedback as emoji reactions on particular news. This web part can also be used on wiki articles or blog posts to take similar reactions. Web part uses concept of 1 to 5 star based rating system(configurable), you can decide low to high based on your preference.
Ideally, we can do some automation using PnP Powershell and PowerAutomate(trigger when item is created ) to add this webpart to any every news that is published.
Ideally, we can do some automation using PnP Powershell and PowerAutomate (trigger when item is created ) to add this web part to any every news that is published.
If you wish to directly use the package in your tenant here is [link](https://github.com/siddharth-vaghasia/public-docs/blob/master/react-emoji-reaction-rating.sppkg) to download.
![WebPart in Action](./assets/EmojiWPinAction.gif)
![Web part in Action](./assets/EmojiWPinAction.gif)
## Features
@ -28,20 +28,29 @@ If you wish to directly use the package in your tenant here is [link](https://gi
* User's rating data would be stored in SP List, below are list of columns and its relevance
1. Title : To store user's display name(not required though)
2. Page Name : To store page on which rating is given by particular user, this will have absolute url of page
3. User : To store user who has given feedback for particular page/news where webpart is added
4. Comment : To store comment provided by user while submitting reaction.
5. Then there are 5 columns Rating1, Rating2, Rating3, Rating4, Rating5 which will store the rating text configured by admin in webpart... Only one of this 5 columns would be populated for single item in list, which is what user has selected as part of giving reaction
1. `Title`: To store user's display name (not required though)
2. `Page Name`: To store page on which rating is given by particular user, this will have absolute url of page
3. `User`: To store user who has given feedback for particular page/news where web part is added
4. `Comment`: To store comment provided by user while submitting reaction.
5. Then there are 5 columns `Rating1`, `Rating2`, `Rating3`, `Rating4`, `Rating5` which will store the rating text configured by admin in web part... Only one of this 5 columns would be populated for single item in list, which is what user has selected as part of giving reaction
* Below is how you can configure emoji's text and its image url
![WebPart in Action](./assets/EmojisConfigurations.png)
![Web part in Action](./assets/EmojisConfigurations.png)
I have added default emoji's images which can be used and uploaded to SharePoint library in the assets folder of this solution.
## Used SharePoint Framework Version
![version](https://img.shields.io/badge/version-1.12.1-green.svg)
## Compatibility
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
![Teams Incompatible](https://img.shields.io/badge/Teams-Incompatible-lightgrey.svg)
![Local Workbench Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg "This solution requires access to a SharePoint list")
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
## Applies to
@ -59,7 +68,7 @@ I have added default emoji's images which can be used and uploaded to SharePoint
Solution|Author(s)
--------|---------
react-emoji-ratings | Siddharth Vaghasia(@siddh_me)
react-emoji-ratings | [Siddharth Vaghasia](https://github.com/siddharth-vaghasia) ([@siddh_me](https://twitter.com/siddh_me))
## Version history
@ -67,19 +76,13 @@ Version|Date|Comments
-------|----|--------
1.0|Sep 04, 2021|Initial release
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
---
## Minimal Path to Awesome
- Clone this repository
- Ensure that you are at the solution folder
- in the command-line run:
- **npm install**
- **gulp serve**
- `npm install`
- `gulp serve`
## References
@ -88,4 +91,19 @@ Version|Date|Comments
- [Publish SharePoint Framework applications to the Marketplace](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/publish-to-marketplace-overview)
- [Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp) - Guidance, tooling, samples and open-source controls for your Microsoft 365 development
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=react-emoji-ratings&authors=@siddharth-vaghasia&title=react-emoji-ratings%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=react-emoji-ratings&authors=@siddharth-vaghasia&title=react-emoji-ratings%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=react-emoji-ratings&authors=@siddharth-vaghasia&title=react-emoji-ratings%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-emoji-ratings" />

View File

@ -0,0 +1,55 @@
[
{
"name": "pnp-sp-dev-spfx-web-parts-react-emoji-ratings",
"source": "pnp",
"title": "Emoji Ratings",
"shortDescription": "Take emoji-based reactions or feedback for a given news/article/post",
"url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-emoji-ratings",
"longDescription": [
"This is sample web part which can be used to take emoji based reaction or feedback for particular news/article/posts.",
"We all know every organizations would be using SharePoint news features for company's internal communications from HR to IT updates and some time annoucements. News created in SharePoint are created as Pages in library. Idea behind this web part is to take employee/user's feedback as emoji reactions on particular news. This web part can also be used on wiki articles or blog posts to take similar reactions. Web part uses concept of 1 to 5 star based rating system(configurable), you can decide low to high based on your preference."
],
"creationDateTime": "2021-09-24",
"updateDateTime": "2021-09-24",
"products": [
"SharePoint",
"Office"
],
"metadata": [
{
"key": "CLIENT-SIDE-DEV",
"value": "React"
},
{
"key": "SPFX-VERSION",
"value": "1.12.1"
},
{
"key": "PNPCONTROLS",
"value": "PropertyFieldCollectionData, PropertyFieldColorPicker, Placeholder"
}
],
"thumbnails": [
{
"type": "image",
"order": 100,
"url": "https://github.com/pnp/sp-dev-fx-webparts/raw/main/samples/react-emoji-ratings/assets/EmojiWPinAction.gif",
"alt": "Web part in action"
}
],
"authors": [
{
"gitHubAccount": "siddharth-vaghasia",
"pictureUrl": "https://github.com/siddharth-vaghasia.png",
"name": "Siddharth Vaghasia"
}
],
"references": [
{
"name": "Build your first SharePoint client-side web part",
"description": "Client-side web parts are client-side components that run in the context of a SharePoint page. Client-side web parts can be deployed to SharePoint environments that support the SharePoint Framework. You can also use modern JavaScript web frameworks, tools, and libraries to build them.",
"url": "https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/build-a-hello-world-web-part"
}
]
}
]

View File

@ -23,11 +23,11 @@
"properties": {
"propertyRatingText": "React emoji reaction rating web part!. How does you like this news/article? ",
"propertyEmojisCollection":[
{"Title":"Wow!","ImagaeUrl":"https://mypersorg.sharepoint.com/sites/PnPSearchDemo/EmojiLibrary//RatingImg1.png"},
{"Title":"Mmm","ImagaeUrl":"https://mypersorg.sharepoint.com/sites/PnPSearchDemo/EmojiLibrary//RatingImg2.png"},
{"Title":"Hmm","ImagaeUrl":"https://mypersorg.sharepoint.com/sites/PnPSearchDemo/EmojiLibrary//RatingImg3.png"},
{"Title":"Meh","ImagaeUrl":"https://mypersorg.sharepoint.com/sites/PnPSearchDemo/EmojiLibrary//RatingImg4.png"},
{"Title":"Pff","ImagaeUrl":"https://mypersorg.sharepoint.com/sites/PnPSearchDemo/EmojiLibrary//RatingImg5.png"}
{"Title":"Wow!","ImageUrl":"https://mypersorg.sharepoint.com/sites/PnPSearchDemo/EmojiLibrary/RatingImg1.png"},
{"Title":"Mmm","ImageUrl":"https://mypersorg.sharepoint.com/sites/PnPSearchDemo/EmojiLibrary/RatingImg2.png"},
{"Title":"Hmm","ImageUrl":"https://mypersorg.sharepoint.com/sites/PnPSearchDemo/EmojiLibrary/RatingImg3.png"},
{"Title":"Meh","ImageUrl":"https://mypersorg.sharepoint.com/sites/PnPSearchDemo/EmojiLibrary/RatingImg4.png"},
{"Title":"Pff","ImageUrl":"https://mypersorg.sharepoint.com/sites/PnPSearchDemo/EmojiLibrary/RatingImg5.png"}
],
/* "propertyListName":"EmojiReactionRating", */

View File

@ -87,11 +87,11 @@ export default class ReactEmojiReactionRatingWebPart extends BaseClientSideWebPa
let listName = this.properties.propertyListName;
console.log("listName: ", listName);
this._spService._createListwithColumns(listName, colListColumns).then((result) => {
console.log(result);
this._spService._createListwithColumns(listName, colListColumns).then((res) => {
console.log(res);
//this.properties.propertyListOperationMessage = result;
//this.context.propertyPane.refresh();
alert(result);
alert(res);
}).catch(error => {
console.log("Something went wrong! please contact admin for more information.", error);
@ -146,8 +146,8 @@ export default class ReactEmojiReactionRatingWebPart extends BaseClientSideWebPa
required: true
},
{
id: "ImagaeUrl",
title: "ImagaeUrl",
id: "ImageUrl",
title: "ImageUrl",
type: CustomCollectionFieldType.url,
required: true

View File

@ -1,16 +1,12 @@
import * as React from 'react';
import styles from './ReactEmojiReactionRating.module.scss';
import { IReactEmojiReactionRatingProps } from './IReactEmojiReactionRatingProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { IReactEmojiReactionRatingState } from './IReactEmojiReactionRatingState';
import { DisplayMode, Environment, EnvironmentType } from '@microsoft/sp-core-library';
import spService from './services/spService';
import { getItemStyles } from 'office-ui-fabric-react/lib/components/ContextualMenu/ContextualMenu.classNames';
import {
FocusZone, IRectangle, List, mergeStyleSets, getTheme,
ITheme, getFocusStyle, ImageFit, TextField, Stack, Label, Rectangle, Button, DefaultButton, PrimaryButton
TextField, Stack, Label, PrimaryButton
} from '@microsoft/office-ui-fabric-react-bundle';
import { IRatingNewItem } from './models/IRatingNewItem';
import Badge from '@material-ui/core/Badge/Badge';
import { Placeholder } from "@pnp/spfx-controls-react/lib/Placeholder";
import { Dialog, DialogFooter, DialogType } from 'office-ui-fabric-react';
@ -58,7 +54,7 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
this.closeDialog = this.closeDialog.bind(this);
}
componentDidMount() {
public componentDidMount() {
if (this.props.enableCount) {
this.getItems();
}
@ -67,7 +63,7 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
}
}
componentDidUpdate(previousProps, previousState) {
public componentDidUpdate(previousProps, previousState) {
if (previousProps.listName !== this.props.listName) {
if (this.props.listName && (this.props.emojisCollection.length > 0)) {
this.setState({ configLoaded: true });
@ -81,7 +77,7 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
}
submitRating(event) {
private submitRating(event) {
let ratingCommnets = this.state.RatingComments ? (this.state.RatingComments).trim() : "";
//let selectedRatingIndex = parseInt(event.target.id);
@ -140,7 +136,7 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
Rating3: "",
Rating4: "",
Rating5: "",
}
};
body[ratingField] = selectedRatingValue;
console.log("body object is: ", body);
@ -156,7 +152,7 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
})
.catch(error => {
console.log("Something went wrong! please contact admin for more information.");
this.ShowDialogError(error, "Something went wrong! please contact admin for more information.")
this.ShowDialogError(error, "Something went wrong! please contact admin for more information.");
});
}
else {
@ -167,7 +163,7 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
})
.catch(error => {
console.log("Something went wrong! please contact admin for more information.");
this.ShowDialogError(error, "Something went wrong! please contact admin for more information.")
this.ShowDialogError(error, "Something went wrong! please contact admin for more information.");
});
}
@ -175,7 +171,7 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
}
async getItems() {
private async getItems() {
console.log("getItems: ", this._currentContext);
let ratingItems = await this._spService.getRatingListItems(this.listName);
@ -204,9 +200,9 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
}
}
let pageRatings = await ratingItems.filter(function (element) {
let pageRatings = await ratingItems.filter((element)=> {
return (element["Pagename"] == window.location.href
)
);
});
Promise.all([
@ -238,9 +234,9 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
});
let userLogin = this._currentContext.pageContext.user.loginName;
let userSelectedRating = await ratingItems.filter(function (element) {
let userSelectedRating = await ratingItems.filter((element)=> {
return (element["Pagename"] == window.location.href
&& (element["User"] == userLogin))
&& (element["User"] == userLogin));
});
console.log("userSelectedRating: ", userSelectedRating[0]);
@ -276,7 +272,7 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
}
let userSelectedRatingIndex;
await this.props.emojisCollection.filter(function (element, tabIndex) {
await this.props.emojisCollection.filter((element, tabIndex)=> {
if ((element["Title"] == currentUserRatingVal)) {
userSelectedRatingIndex = tabIndex;
return tabIndex;
@ -291,23 +287,23 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
}
async getRatingCount(items: any[], colName: string, colValue: string) {
let ratingCount = await items.filter(function (element) {
private async getRatingCount(items: any[], colName: string, colValue: string) {
let ratingCount = await items.filter((element)=> {
return element[colName] == colValue;
}).length
}).length;
return ratingCount;
}
selectedRating(event) {
private selectedRating(event) {
let selectedRatingIndex = event.target.tabIndex;
let selectedRatingValue = event.target.title;
this.setState({
selectedRatingIndex: selectedRatingIndex,
selectedRatingValue: selectedRatingValue
})
});
}
private handleChange(event: any, newValue: string) {
@ -388,7 +384,7 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
{this.props.enableCount ? (
<>
<Badge color="secondary" overlap="circular" badgeContent={this.state[tabIndex]}>
<img src={ratingItem.ImagaeUrl}
<img src={ratingItem.ImageUrl}
className={this.state.selectedRatingIndex == tabIndex ? styles.selectedEmoji : styles.stackImage}
title={ratingItem.Title}
tabIndex={tabIndex}
@ -400,7 +396,7 @@ export default class ReactEmojiReactionRating extends React.Component<IReactEmoj
<Label className={styles.labelClass}>{ratingItem.Title}</Label>
</>) : (
<>
<img src={ratingItem.ImagaeUrl}
<img src={ratingItem.ImageUrl}
className={this.state.selectedRatingIndex == tabIndex ? styles.selectedEmoji : styles.stackImage}
title={ratingItem.Title}
tabIndex={tabIndex}

View File

@ -128,18 +128,18 @@ export default class spService {
}).catch(error => {
console.log(error);
});
return "List with required columns created."
return "List with required columns created.";
}
}
else {
return "List alreay exist"
return "List alreay exist";
}
}
public async _checkList(listName: string) {
let filterList = `Title eq '${listName}'`
let filterList = `Title eq '${listName}'`;
let boolResult: boolean = false;
let getList = await sp.web.lists.filter(filterList).get()
let getList = await sp.web.lists.filter(filterList).get();
if (getList.length > 0) {
return boolResult = true;
}

View File

@ -0,0 +1,98 @@
{
"bundles": {
"multi-screen-web-part": {
"dependencies": [
{
"componentId": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"componentName": "@microsoft/sp-core-library",
"componentVersion": "1.12.1",
"isDirectDependency": true
},
{
"componentId": "01c4df03-e775-48cb-aa14-171ee5199a15",
"componentName": "tslib",
"componentVersion": "1.10.0",
"isDirectDependency": false
},
{
"componentId": "2e09fb9b-13bb-48f2-859f-97d6fff71176",
"componentName": "@ms/odsp-core-bundle",
"componentVersion": "1.1.13",
"isDirectDependency": false
},
{
"componentId": "73e1dc6c-8441-42cc-ad47-4bd3659f8a3a",
"componentName": "@microsoft/sp-lodash-subset",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "974a7777-0990-4136-8fa6-95d80114c2e0",
"componentName": "@microsoft/sp-webpart-base",
"componentVersion": "1.12.1",
"isDirectDependency": true
},
{
"componentId": "8217e442-8ed3-41fd-957d-b112e841286a",
"componentName": "@ms/sp-telemetry",
"componentVersion": "0.19.2",
"isDirectDependency": false
},
{
"componentId": "467dc675-7cc5-4709-8aac-78e3b71bd2f6",
"componentName": "@microsoft/sp-component-base",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "e40f8203-b39d-425a-a957-714852e33b79",
"componentName": "@microsoft/sp-dynamic-data",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "78359e4b-07c2-43c6-8d0b-d060b4d577e8",
"componentName": "@microsoft/sp-diagnostics",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "1c4541f7-5c31-41aa-9fa8-fbc9dc14c0a8",
"componentName": "@microsoft/sp-page-context",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "229b8d08-79f3-438b-8c21-4613fc877abd",
"componentName": "@microsoft/load-themed-styles",
"componentVersion": "0.1.2",
"isDirectDependency": false
},
{
"componentId": "c07208f0-ea3b-4c1a-9965-ac1b825211a6",
"componentName": "@microsoft/sp-http",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "1c6c9123-7aac-41f3-a376-3caea41ed83f",
"componentName": "@microsoft/sp-loader",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"componentName": "react",
"componentVersion": "16.9.0",
"isDirectDependency": true
},
{
"componentId": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"componentName": "react-dom",
"componentVersion": "16.9.0",
"isDirectDependency": true
}
]
}
}
}

View File

@ -0,0 +1,63 @@
{
"id": "f9a07202-7f8f-4944-a02c-1fd20b508207",
"alias": "MultiScreenWebPart",
"componentType": "WebPart",
"version": "0.0.1",
"manifestVersion": 2,
"requiresCustomScript": false,
"supportedHosts": [
"SharePointWebPart",
"SharePointFullPage",
"TeamsTab"
],
"preconfiguredEntries": [
{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70",
"group": {
"default": "Other"
},
"title": {
"default": "MultiScreenWebPart"
},
"description": {
"default": "MultiScreenWebPart description"
},
"officeFabricIconFontName": "Page",
"properties": {
"description": "MultiScreenWebPart"
}
}
],
"loaderConfig": {
"internalModuleBaseUrls": [
"<!-- PATH TO CDN -->"
],
"entryModuleId": "multi-screen-web-part",
"scriptResources": {
"multi-screen-web-part": {
"type": "path",
"path": "multi-screen-web-part.js"
},
"@microsoft/sp-core-library": {
"type": "component",
"id": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"version": "1.12.1"
},
"@microsoft/sp-webpart-base": {
"type": "component",
"id": "974a7777-0990-4136-8fa6-95d80114c2e0",
"version": "1.12.1"
},
"react": {
"type": "component",
"id": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"version": "16.9.0"
},
"react-dom": {
"type": "component",
"id": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"version": "16.9.0"
}
}
}
}