“We keep moving forward, opening new doors, and doing new things, because we’re curious and curiosity keeps leading us down new paths.”
— Walt Disney
So, I have been scouring the Interwebs for the different ways people have built and displayed the results of various user rating systems, looking for the best and easiest way to display the average rating based on all of the feedback to date. I wanted it to be graphic and intuitive, but also support fractional values. Even though the choices are whole numbers, once you start aggregating the responses from multiple individuals, the end result is going to end up falling somewhere in between, and on my Generic Feedback Widget, I wanted to be able to show that level of accuracy in the associated graphic.
The out-of-the-box display of a Live Feed Poll show how many votes were received from each of the possible options. That didn’t seem all that interesting to me, as I was looking for a single number that represented the average score, not how many votes each possibility received. Then I came across this.
That solution did not support the fractional graphic, but it did include the breakdown similar to the stock Live Feed Poll results, which got me rethinking my earlier perspective on not having any use for that information. After seeing this approach, I decided that it actually would be beneficial to make this available, but only on request. My thought was to display the graphic, the average rating, and the number of votes, and then have a clickable link for the breakdown that you could use if you were interested in more details.
All of that seemed rather complex, so I decided that I would not try to wedge all of that functionality into the Generic Feedback Widget, but would instead build a separate component to display the rating and then just use that component in the widget. This looked like a job for another Angular Provider like the ones that I used to create my Service Portal Form Fields and Service Portal Widget Help. I was thinking that it could something relatively simple to use, with typical usage looking something like this:
<snh-rating values="20,6,15,63,150"></snh-rating>
My theory on the values attribute was that as long as I had the counts of votes for each of the options, I could generate the rest of the data needed such as the total number of votes and the total score and the average rating. The trouble, of course, was that the function that I built to get the info on the votes cast so far did not provide this information. So, back the drawing board on that little doo-dad …
I actually wanted to use a GlideAggregate for this originally, but couldn’t do it when dot-walking the option.order wasn’t supported. But now that I have to group by option to get a count for each, that is no longer an issue and I can actually rearrange things a bit and not have to loop through every record to sum up the totals. Here’s the updated version that returns an array of votes for each possible rating:
currentRating: function(table, sys_id) {
var rating = [0, 0, 0, 0, 0];
var pollGR = new GlideRecord('live_poll');
if (pollGR.get('question', table + ':' + sys_id + ' Rating')) {
var castGA = new GlideAggregate('live_poll_cast');
castGA.addAggregate('COUNT');
castGA.addQuery('poll', pollGR.getUniqueValue());
castGA.groupBy('option');
castGA.orderBy('option.order');
castGA.query();
while (castGA.next()) {
var i = castGA.getValue('option.order') - 1;
rating[i] = parseInt(castGA.getAggregate('COUNT'));
}
}
return rating;
},
That should get me the data that I will need to pass to the new snh-rating tag. Now all I have to do is build the Angular Provider behind that tag to turn those values into a nice looking presentation. That sounds like a good topic for a next installment!