Muchas veces he escrito sobre la capacidad que existe en SharePoint de emplear utilidades ya implementadas por el propio servidor. Estos componentes nos facilitan mucho el desarrollo y, por regla general, son bastante configurables.
En esta ocasión, vamos a destripar el componente de «Rating» /Valoración que se le puede agregar a las bibliotecas de SharePoint de documentos y noticias de forma simple. Un requerimiento muy habitual en las Intranet es poder otorgar la funcionalidad de valorar la noticia por parte del usuario que la está leyendo. Y a través este componente lo podemos hacer sin problemas.
¿Empezamos?
Para empezar a utilizar este componente, lo podemos activar a través de la interfaz gráfica. Vamos a la configuración de la biblioteca de documentos/ páginas y activar el rating.
El rating puede ser de dos formas: Like o Estrellas.
Activarlo mediante la interfaz gráfica puede ser una solución que utilicen los usuarios avanzados/usuarios finales de SharePoint, pero en nuestros desarrollos debemos de dotar de la calidad de realizarlo sin hacer click (o minimizar el número de clicks a realizar). Para ello, vamos a activar esta funcionalidad con el siguiente script de PowerShell:
Param ( [Parameter(Mandatory=$true)] [string]$UrlWeb = $(Read-Host -Prompt "Web Url") ) Add-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue $web=Get-SPWeb $UrlWeb; $list=$web.Lists["Páginas"]; if($list -ne $null) { Write-Host $list.Title "not null"; $assembly=[System.Reflection.Assembly]::Load("Microsoft.SharePoint.Portal, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c") $reputationHelper =$assembly.GetType("Microsoft.SharePoint.Portal.ReputationHelper"); $bindings = @("EnableReputation", "NonPublic", "Static"); [System.Reflection.BindingFlags]$flags = [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::NonPublic; $methodInfo = $reputationHelper.GetMethod("EnableReputation", $flags); #For enabling Ratings $values = @($list, "Ratings", $false); #OR for enabling Likes #$values = @($list, "Likes", $false); $methodInfo.Invoke($null, @($values)); #For disable Rating or Likes <#$methodInfo = $reputationHelper.GetMethod("DisableReputation", $flags); $disableValues = @($list); $methodInfo.Invoke($null, @($disableValues));#> }
Una vez lo tenemos activado, tenemos que ver cómo poder utilizar este componente tanto en los DisplayTemplate como en nuestro código C# bien en PageLayout o nuestros WebParts.
Utilizarlo en DisplayTemplate
En primer lugar, nos hemos creado un Módulo con todas las funcionalidades que tenemos para obtener las estrellitas y para generar el HTML que renderizará el valor de las mismas. El código seria el siguiente:
var Encamina = Encamina || {}; Encamina.Ratings = function () { var ratings = { termStoreName: '', termSetId: '', currentTerm: '', root: this, MenuItem: function (title, url) { }, currentMenuItems: new Array(), init: function (termName, termId, current) { this.termStoreName = termName; this.termSetId = termId; this.currentTerm = current; }, GenerateRatingStars: function (rating, ratingCount) { var decRating = rating.value - Math.floor(rating.value); var totalStars = 5; var html = ""; if (ratingCount == "") { ratingCount = 0; } var filledImage = "/_layouts/15/images/RatingsSmallStarFilled.png"; var emptyImage = "/_layouts/15/images/RatingsSmallStarEmpty.png"; var halfImage = "/_layouts/15/images/RatingsSmallStarLeftHalfFilled.png"; html += "<div class='ms-comm-noWrap'><span id='averageRatingElement-" + rating + "'>"; for (var i = 0; i < totalStars; i++) { var count = i + 1; var img = emptyImage; if (count <= rating) { img = filledImage; } else if (decRating > 0) { img = halfImage; decRating = 0; } html += "<span class='ratingsImageContainer star-' data-starnumber='" + count + "'>"; html += "<img id='averageRatingElement-" + rating + "-img-" + count + "' src='" + img + "'/>"; html += "</span>"; } html += "</span><span class='ms-comm-ratingSeparator'/>"; html += "<span class='ms-comm-ratingCountContainer' id='averageRatingElement-" + ratingCount + "-count'>"; html += " " + ratingCount + "</span></span></div>"; return html; }, UpdateRating: function (siteUrl, listId, listItemId, context) { return function (element, arguments) { var rating = element.currentTarget.dataset.starnumber; function RatingSuccess(sender, args) { SP.UI.Notify.addNotification('Valoración actualizada', false); var queryState = new Srch.QueryState(); var queryStateArgs = new Srch.QueryEventArgs(queryState); debugger; context.ClientControl.raiseQueryReadyEvent(queryStateArgs); } function RatingFailure(sender, args) { SP.UI.Notify.addNotification('Error actualizando valoración:' + args.get_message(), false); } if (rating != null && rating != "" && !isNaN(rating)) { var spCtx = new SP.ClientContext(siteUrl + "/AlDia/Circulares"); Microsoft.Office.Server.ReputationModel.Reputation.setRating(spCtx, listId, listItemId, parseInt(rating)); spCtx.executeQueryAsync(Function.createDelegate(this, RatingSuccess), Function.createDelegate(this, RatingFailure)); } }; } }; return ratings; }();
Una vez tenemos estos valores, dentro de la plantilla del DisplayTemplate, deberemos de indicar la siguiente llamada:
<!--#_ function SearchRating(avgRating, ratingCount, selector, siteUrl, listId, listItemId, context) { var stars = $("#" +selector+ " .ratingsImageContainer"); stars.on("click", Encamina.Ratings.UpdateRating(siteUrl, listId, listItemId, context)); } var AverageRating = $getItemValue(ctx, "AverageRating"); var RatingCount = $getItemValue(ctx, "RatingCount"); var RatingDisplay = Encamina.Ratings.GenerateRatingStars(AverageRating, RatingCount); AddPostRenderCallback(ctx, function() { SearchRating(AverageRating, RatingCount, ratingsId, siteUrl, listId, listItemId, ctx); }); _#-->
Utilizarla en los PageLayout
Para utilizarlo dentro de los PageLayouts, primero debemos registrar el componente en la cabecera del ASPX:
<%@ Register TagPrefix="SharePointPortalControls" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
A continuación, con añadir la siguiente línea ya tendremos disponible las estrellitas en nuestro desarrollo:
<SharePointPortalControls:AverageRatingFieldControl ID="PageRatingControl" FieldName="AverageRating" runat="server"/>
Aunque… ¡¡esto no podía ser tan sencillo como parece!! Existe un bug reconocido: la primera vez que se carga la página con las estrellitas no se muestran las imágenes en Internet Explorer. Esto es debido al orden de carga de los ficheros de JavaScript propios de SharePoint. ¡SOLUCIÓN! Tenemos que añadir una función JavaScript, que hará que una vez que esté cargada la página, muestre las estrellas. Para ello podemos utilizar el siguiente código:
<script type="text/javascript"> function fixIE10StarRatingIssue() { if (SP.UI.Reputation != null) { SP.UI.Reputation.RatingsHelpers.$c(false); jQuery('.votacion > script').each(function () { eval($(this).text()); }); } } _spBodyOnLoadFunctionNames.push('fixIE10StarRatingIssue'); </script>
Referencias
http://almondlabs.com/blog/adding-interactive-ratings-to-sharepoint-2013-search-results-part-2/
http://weblogs.asp.net/bsimser/adding-ratings-and-comments-to-sharepoint-publishing-pages
http://community.rightpoint.com/blogs/viewpoint/archive/2014/10/19/add-comments-and-ratings-to-a-sharepoint-2013-page-layout-using-design-manager.aspx