How to store ratings from client

Hi … me again :slight_smile:

What is the mechanism to store ratings from javascript on the client side? Does the Ratings API expose some REST-Interface? Where is it located? I am trying to understand the sources from the Ratings Application …

  const postURL = new XWiki.Document('RatingsUIX', 'XWiki.Ratings').getURL('get');

  var setVote = function (wrapper, reference, vote) {
    $.post(postURL, {
      "outputSyntax": "plain",
      "vote": vote,
      "doc": reference,
      "form_token": xm.form_token
    }).then(data => {
            // ...
    });

But how do I address a certain Ratings Manager?

Thanks in advance for your any hint on this?

Holger

There’s currently no REST API for the Ratings. Maybe a future improvment to add but we never really had the need until now.

The script you’re showing is actually relying on a velocity script defined directly in a document: calling a POST to the page XWiki.Ratings.RatingsUIX leads to enter in that script, see: the file on github

You could implement the same kind of script in a page, which would use the proper script service call using your own ratings manager.

Ah, thanks! I think I understand that … I’ll try

Hi …

now I have implemented a similar script in groovy, that stores the rating:

{{groovy}}
import java.util.stream.Collectors;
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import org.xwiki.model.reference.ObjectReference

if (request.method == "POST" && xcontext.action == "get") {
  def body = new BufferedReader(new InputStreamReader(request.getInputStream()))
  .lines().collect(Collectors.joining("\n"));
  def payload = new JsonSlurper().parseText(body)

  if (payload.doc != null && payload.id != null) {
    def ref = services.model.resolveObject(payload.doc + "^" + payload.id);
    def user = xcontext.getUser();
    def vote = services.ratings.aufgaben.setRating(ref, payload.vote)
    def average = services.ratings.aufgaben.getAverageRating(ref).get()
    def json = [
      ref: "" + ref,
      vote: payload.vote,
      user: user,
      averageVote: average.averageVote,
      totalVote: average.totalVote,
    ]
    print JsonOutput.prettyPrint(JsonOutput.toJson(json))
  }
  else {
    def user = xcontext.getUser();
    def json = [
      message: 'doc and/or id missing',
      body: body
    ]
    print JsonOutput.prettyPrint(JsonOutput.toJson(json))
  }
}
{{/groovy}}

It’s callable by means of a fetch:

  var sendRate = function (rid, vote) {
    fetch(new XWiki.Document('WebHome', 'Macros.Aufgabenbewertung').getURL('get') + "?outputSyntax=plain", {
      method: "POST",
      headers: { "Content-Type": "application/json"},
      body: JSON.stringify({
        vote: vote,
        doc: XWiki.currentDocument.space + ".WebHome",
        id: rid,
        form_token: document.documentElement.getAttribute("data-xwiki-form-token")
      })
    }).then(data => {
            console.log(data.json())
    });
  }

It seems to work. However, when I try to read the average rating with #set($average = $services.ratings.aufgaben.getAverageRating($ref)), I do not get the expected value. My explorations (getCurrentUserRatings) reveal, that there are actually multiple ratings stored with the same [object reference / user reference] combination:

reference = [Object xwiki:Sandbox.WebHome^test], vote = [4], scale = [5],
reference = [Object xwiki:Sandbox.WebHome^test], vote = [1], scale = [5]

I’d expect, that a certain user can only give one single vote per object reference!?

Now I wonder, if it is actually possible, to store a rating with arbitrary object references, for which there are no real objects? Sandbox is an existing page, but there is no object named test contained in that page.

That’s indeed what’s expected, I do have a check for this in the implementation of the SolrRatingsManager, see the code and AFAICS I normally reuse the data with same ID. This has been tested with the standard Ratings Application, so I’d be surprised it doesn’t work.
Maybe it’s related to usage of an xobject reference I never really tried that usecase…

Can you open a ticket on jira for this?

There’s no check whatsoever about the existence or not of the reference when performing the ratings.

Just a side note: you can use xwiki-meta module to access it, see: https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/FrontendResources/JavaScriptAPI/#HGetsomeinformationaboutthecurrentdocument

Again, thanks for your immediate help!

I just opened two tickets: XWIKI-21576 and XWIKI-21577