Ratings is an essential component of skills which provides the developers an insight into how the SUSI Skill is functioning and how to further improve it which ultimately leads to great user experience so this was the motivation to allow users to be able to rate skills, once the rating system is implemented we need to show some statistics like average rating, total users who have rated the skills etc on the skill page for each skill, and this will also enable users to get top rated skills and thus users can get to use the best skills rated by the community. So we implemented a rating section to SUSI SKILL CMS
Implementation
Server –
- Two APIs were implemented by the analytics team on the server which allows the user to rate skill and fetch rating for each skill.
- To rate the skill (Sample)
/cms/getSkillRating.json?model=general&group=Knowledge&language=en&skill=aboutsusi&callback=pc&_=1525446551181
- To get the ratings data for any skill (Sample)
/cms/fiveStarRateSkill.json?model=general&group=Knowledge&language=en&skill=aboutsusi&stars=3&callback=p&_=1526813916145
- To rate the skill (Sample)
CMS –
-
- When visiting any skill make an ajax call to the server to fetch the skill data for the visited skill. The call takes in the URL from which we have to fetch data from and of course a datatype which is jsonp since server returns data in the JSON format, when the request succeeds we save the received rating to the application state and in the case or any errors we log the error for developers to debug.
// Fetch ratings for the visited skill $.ajax({ url: skillRatingUrl, jsonpCallback: 'pc', dataType: 'jsonp', jsonp: 'callback', crossDomain: true, success: function (data) { self.saveSkillRatings(data.skill_rating) }, error: function(e) { console.log(e); } });
-
- Save the fetched data to the application state, this data saved in the state will be used in several components and graph present on the ratings section.
- Save the fetched data to the application state, this data saved in the state will be used in several components and graph present on the ratings section.
saveSkillRatings = (skill_ratings) => { this.setState({ skill_ratings: data }) }
- Plug in the data received to the Bar chart component to visualize how ratings are divide.
- Import the required components on the top of the file from the recharts library which provides us with several interactive charts.
-
- Plug the data to the BarChart component through the data prop and render them to the page, this data is coming from the application state which we saved earlier. After that we define keys and styling for the X-Axis and Y-Axis and an interactive tooltip which shows up on hovering over any bar of that chart. We have 5 bars on the chart for each star rating all of different and unique colors and labels which appear on the right of each bar.
import {BarChart, Cell, LabelList, Bar, XAxis, YAxis, Tooltip} from 'recharts';
<div className="rating-bar-chart"> <BarChart layout='vertical' width={400} height={250} data={this.state.skill_ratings}> <XAxis type="number" padding={{right: 20}} /> <YAxis dataKey="name" type="category"/> <Tooltip wrapperStyle={{height: '60px'}} /> <Bar name="Skill Rating" dataKey="value" fill="#8884d8"> <LabelList dataKey="value" position="right" /> { this.state.skill_ratings .map((entry, index) => <Cell key={index} fill={ ['#0088FE', '#00C49F', '#FFBB28', '#FF8042', '#FF2323'][index % 5] }/>) } </Bar> </BarChart> </div>
- Display the average rating of the skill along with the stars
-
- Import the stars component from the react-ratings-declarative component.
import Ratings from 'react-ratings-declarative';
- Render the average ratings and the stars component which is available in the app state as saved before.
<div className="average"> Average Rating <div> {this.state.avg_rating ? this.state.avg_rating : 2.5} </div> <Ratings rating={this.state.avg_rating || 2.5} widgetDimensions="20px" widgetSpacings="5px" > <Ratings.Widget /> <Ratings.Widget /> <Ratings.Widget /> <Ratings.Widget /> <Ratings.Widget /> </Ratings> </div>
- Import the stars component from the react-ratings-declarative component.
-
- Display the total no of people who rated the skill, again, by using the ratings data saved in the state and calculating the total users who rated the skill by using a reduce function in ES6.
<div className="total-rating"> Total Ratings <div> {this.state.skill_ratings.reduce((total, num) => { return total + num.value }, 0)} </div> </div>
Outcome –
I hope this post helped you in understanding how the rating system is implemented in the CMS.
References –
- Check out http://recharts.org/ which is used to render charts in the app.
- Reduce function in javascript https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce.
- API implementation in the server in this https://github.com/fossasia/susi_server/pull/730
- See sample analytics for the assistant apps https://developers.google.com/actions/distribute/directory