martes, 5 de octubre de 2010

Blogs en SharePoint 2010 y rating

Permitir a tus usuarios valorar los posts de un blog de SharePoint 2010 y mostrar estas valoraciones por pantalla es un requerimiento bastante habitual que, por defecto, no está soportado. Existen muchas maneras de poner esto en marcha, y se pueden encontrar algunas soluciones que te ofrecen esta y otras muchas funcionalidades (por ejemplo, CKS). No obstante, si sólo queremos habilitar el rating y no queremos complicarnos la vida, tenemos una manera muy simple de hacerlo.

Para empezar, accedemos a la gestión de la lista de posts de nuestro blog y, una vez ahi, seleccionamos configuración de la lista.

image

En la configuración de la lista veremos una opción para establecer la configuración de las valoraciones o ratings.

image 

Una vez ahí podremos confirmar que permitimos valorar los elementos de esta lista y guardar la configuración.

image

En estos momentos nuestra lista está preparada para recibir valoraciones y, utilizando las vistas de la lista y editando las propiedades de los posts podríamos valorarlos y ver las valoraciones medias. Si queremos hacer esto de una manera más elegante, necesitamos permitir realizar las valoraciones desde la propia página del post y ver las valoraciones medias desde la lista. Para hacer eso, podemos utilizar SharePoint Designer.

Accedemos a All Files –> Lists –> Posts –> Post.aspx y editamos el fichero en modo avanzado

image

Una vez ahí necesitamos, primero, registrar el control de valoraciones al inicio de la página, insertando el siguiente código:

<%@ Register Tagprefix="SharePointPortalControls" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

Después, en algún lugar de la página (yo he decidido ponerlo dentro del DIV con ID BlogRSSNav pero podéis decidir vosotros mismos) necesitáis añadir el control AverageRatingFieldControl.

<div id="BlogRSSNav">
    <SharePointPortalControls:AverageRatingFieldControl id="PageRatingControl" FieldName="Rating (0-5)" runat="server" />
</div>

Una vez hecho esto ya tendréis la posibilidad de enviar valoraciones desde la propia página del post, tal y como muestra la figura:

image

Poner esta información en el listado de la página inicial es algo más complejo y va a requerir que tengáis conocimientos de XSLT. Para hacerlo deberíais editar la página default.aspx de la raíz del sitio con SharePoint Designer, localizar el XsltListViewWebPart que muestra la lista de posts (es el segundo) y modificar la definición del XML.

Primero, en la lista de ViewFields tendréis que añadir el siguiente campo:

<FieldRef Name="AverageRating"/>

Para finalizar, puedes mostrar el campo allá donde más te convenga, dentro del nodo xsl, utilizando el siguiente código:

<xsl:value-of select="$thisNode/@AverageRating"/>

Evidentemente esto es únicamente parte de la solución porque aunque tengas todo perfectamente configurado únicamente verás el valor numérico. A partir de aquí, con algunos conocimientos de XSLT podrás montar automáticamente una lista de estrellas o cualquier otro elemento que quieras utilizar para mostrar las valoraciones. Si, además de todo esto, necesitas disponer del control interactivo para valorar posts desde el propio listado os recomiendo que editéis con SharePoint Designer alguna de las vistas que contengan el campo AverageRating como, por ejemplo, AllPosts.aspx.

Editado el 06/10/2010

Para aclarar algunas dudas, añado el código xsl que sería necesario para mostrar la valoración media justo delante del título del post en la página de inicio del blog. Editáis la página con SharePoint Designer 2010 y buscáis el siguiente código:

</XmlDefinition>
<DataFields>
</DataFields>
 
</WebPartPages:XsltListViewWebPart>

Y justo después del cierre del nodo DataFields introducís el siguiente código:

<Xsl>
    <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal" xmlns:o="urn:schemas-microsoft-com:office:office"> 
        <xsl:include href="/_layouts/xsl/blog.xsl"/> 
        <xsl:include href="/_layouts/xsl/internal.xsl"/> 
        <xsl:param name="AllRows" select="/dsQueryResponse/Rows/Row[$EntityName = '' or (position() &gt;= $FirstRow and position() &lt;= $LastRow)]"/>
        <xsl:param name="dvt_apos">&apos;</xsl:param>
        <xsl:template mode="Item" match="Row[../../@TemplateType='301' and (../../@BaseViewID='0' or ../../@BaseViewID='7' or ../../@BaseViewID='8' or ../../@BaseViewID='9')]" ddwrt:ghost="">
        <xsl:param name="Fields" select="."/>
        <xsl:param name="Collapse" select="."/>
        <xsl:param name="Position" select="1"/>
        <xsl:param name="Last" select="1"/>
        <xsl:variable name="ShowBody"><xsl:if test="../../@BaseViewID='0' or ../../@BaseViewID='7'">1</xsl:if></xsl:variable>
        <xsl:variable name="ShowTopDate"><xsl:if test="../../@BaseViewID='0' or ../../@BaseViewID='7'">1</xsl:if></xsl:variable>
        <xsl:variable name="ShowDrafts"><xsl:if test="../../@BaseViewID='7'">1</xsl:if></xsl:variable>
        <xsl:variable name="thisNode" select="."/>
        <xsl:if test="$ShowDrafts=1 or $thisNode/@_ModerationStatus. = 0">
            <table>
              <tr class="ms-blogpostdatecol" valign="top">
                  <td class= "ms-leftblogdate">
                    <div id="PostDateTopBox{generate-id()}" class="ms-postcalendardateboxtop">
                    </div>
                    <xsl:if test="$MasterVersion = 4">
                        <div id="PostDateBottomBox{generate-id()}" class="ms-postcalendardateboxbottom" style="overflow-x:hidden">
                            <div>
                                <xsl:value-of select="$thisNode/@PublishedDate.MonthDayOnly" disable-output-escaping="yes" />
                            </div>
                        </div>
                    </xsl:if>
                    <xsl:if test="$MasterVersion != 4">
                        <div id="PostDateBottomBox" class="ms-postcalendardateboxbottom" style="overflow-x:hidden;font-size:0.8em">
                            <div>
                            <xsl:value-of select="$thisNode/@PublishedDate.MonthDayOnly" disable-output-escaping="yes" />
                            </div>
                        </div>
                    </xsl:if>      
                  </td>
                  <td class = "ms-rightblogpost">
                    <table dir="None" cellspacing="0" cellpadding="0" width="100%" border="0">
                      <tbody>
                        <tr>
                          <td class="ms-PostTitle">
                                                          
                            <xsl:value-of select="$thisNode/@AverageRating"/>
                            
                            <xsl:value-of select="$Fields[@Name='AverageRating']" disable-output-escaping="yes" />
                            <a href="{$HttpVDir}/{$thisNode/../@resource.wss.lists_Folder}/{$thisNode/../@resource.wss.blogpost_Folder}/Post.aspx?ID={$thisNode/@ID}">
                              <xsl:apply-templates select="$Fields[@Name='Title']" mode="PrintField">
                                <xsl:with-param name="thisNode" select="$thisNode"/>
                                <xsl:with-param name="Position" select="$Position"/>
                              </xsl:apply-templates>
                            </a>
                          </td>
                              <xsl:if test="../../@BaseViewID='7'">
                                <xsl:if test="($thisNode/../@value.listpermission.EditListItems = '1' and (($thisNode/../@value.listpermission.ManageLists  = '1') or ($XmlDefinition/List/@WriteSecurity = '2' and $thisNode/@Author.id = $Userid) or ($XmlDefinition/List/@WriteSecurity != '2')))">
                                  <td align="right" class="ms-blogedit">
                                    <a href="javascript:" onclick="javascript:ShowPopupDialog('{$HttpVDir}/{$thisNode/../@resource.wss.lists_Folder}/{$thisNode/../@resource.wss.blogpost_Folder}/EditPost.aspx?ID={$thisNode/@ID}&amp;Source={$HttpVDir}%2Fdefault.aspx');">
                                      <xsl:value-of select="'Edit'" />
                                    </a>
                                  </td>
                                </xsl:if>
                              </xsl:if>
                        </tr>
                      </tbody>
                    </table>
                    <div class="ms-PostFooter">
                      <xsl:for-each select="$Fields">            
                        <xsl:if test="@Name!='Title' and @Type!='Note' and not(@Name='PostCategory' and $thisNode/@PostCategory='')">
                              <xsl:choose>
                                <xsl:when test="@Name='Author'"><span class="ms-postfootercolor"><xsl:value-of select="'by '"/></span><xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;</xsl:text><xsl:value-of select="$thisNode/@Author.span" disable-output-escaping="yes" /></xsl:when>
                                <xsl:when test="@Name='PublishedDate'"><xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;&amp;nbsp;</xsl:text><span class="ms-postfootercolor"><xsl:value-of select="'on'"/><xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;</xsl:text><xsl:value-of select="$thisNode/@PublishedDate" /></span></xsl:when>                
                              </xsl:choose>
                        </xsl:if>
                      </xsl:for-each>
                    <div>
                        <xsl:for-each select="$Fields">            
                  <xsl:if test="@Name='PostCategory' and not ($thisNode/@PostCategory='')">
            <xsl:value-of select="'Category'" />:<xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;</xsl:text><xsl:apply-templates select="$Fields[@Name='CategoryWithLink']" mode="Computed_body"><xsl:with-param name="thisNode" select="$thisNode"/></xsl:apply-templates>
            </xsl:if>
        </xsl:for-each>
        </div>
      </div>
        <xsl:if test="$ShowBody=1">
          <div class="ms-PostBody">
            <div>
              <xsl:apply-templates select="$Fields[@Name='Body']" mode="PrintField">
                <xsl:with-param name="thisNode" select="$thisNode"/>
                <xsl:with-param name="Position" select="$Position"/>
              </xsl:apply-templates>
            </div>
          </div>
        </xsl:if>
        <div class="ms-PostFooter">
              <xsl:for-each select="$Fields">            
                <xsl:if test="@Name ='Permalink' or @Name ='EmailPostLink' or @Name ='NumCommentsWithLink'">
                    <xsl:choose>
                          <xsl:when test="@Name='Permalink' or @Name='EmailPostLink' or @Name='NumCommentsWithLink'"><xsl:apply-templates select="." mode="PrintFieldWithDisplayFormLink"><xsl:with-param name="thisNode" select="$thisNode"/><xsl:with-param name="Position" select="$Position"/></xsl:apply-templates><xsl:if test="@Name='Permalink' or @Name='EmailPostLink'"><xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;|&amp;nbsp;</xsl:text></xsl:if></xsl:when>
                          <xsl:when test="$thisNode/@*[name()=current()/@Name]!=''"><xsl:apply-templates select="." mode="PrintFieldWithDisplayFormLink"><xsl:with-param name="thisNode" select="$thisNode"/><xsl:with-param name="Position" select="$Position"/></xsl:apply-templates><xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;|&amp;nbsp;</xsl:text></xsl:when>
                    </xsl:choose>
            </xsl:if>
          </xsl:for-each>
        </div>
          </td>
    </tr>
    </table>
    </xsl:if>
  </xsl:template></xsl:stylesheet>
</Xsl>

 

11 comentarios:

Ignasi Tebé Tena dijo...

Vaya!! Con SharePoint Designer!! Si no fuera por las líneas de código, diría que te estás pasando al lado del ITPro...

;-D

David Martos dijo...

Jejeje, por eso las he metido Ignasi, la cabra tira al monte...

Anónimo dijo...

Hola David,

Muy bueno tu articulo, una consulta es posible visualizar las estrellas de forma gráfica en default.aspx de la misma manera como se visualiza en allposts.aspx.

La idea es que el usuario pueda ver y botar de inmediato sin registrar un comentario.

Muchas gracias,

Saludos

David Martos dijo...

Hola,

sí que puedes hacer lo que comentas, pero yo no lo haría en la página default.aspx ya que ahí estás valorando la página inicial del blog, independientemente del post que estés leyendo. En el artículo se valora desde la página post.aspx, que es la página de detalle del post, y que no requiere que pongas ningún comentario para hacer la valoración.

Anónimo dijo...

David, muchas Gracias por tu respuesta.

Solo para estar seguro, y para ver si me explique bien, si en default.aspx tengo tres post es posible que el rating de las estrellas de forma gráfica aparezca en cada uno de ellos, por ejemplo al lado de la fecha de cada uno para poder votar directamente sin ingresar a la sección comentario.

Nuevamente muchas gracias

David Martos dijo...

Lo que necesitas es posible, pero bastante más complicado de hacer que lo que se explica en este artículo. De todas maneras puedes adaptar el proceso para incluir en cada item de la vista de la página default.aspx el código necesario para realizar las valoraciones directamente desde el listado. Otra opción que tienes es desarrollar un webpart que consulte la lista de posts y, mediante el modelo de objetos de SharePoint te permita realizar la misma acción.

Anónimo dijo...

ok David, muchas gracias por tu ayuda.

Jose Emmanuel dijo...

Espero funciones al igual con imagenes. Gracias buen post.

Eliana dijo...

Hola David, excelente post! Yo estoy tratando de hacer lo mismo pero utizando una visual WebPart. Tienes idea de como puedo mostrar las estrellas de la lista en este caso? Aun despues de obtener los valores de la lista con SPQuery las estrellas no se activan dentro del repeater. Alguna sugerencia?

Muchas gracias de antemano,
Saludos

Francis Urteaga dijo...

Estimado,
Estoy tratando de implementar lo que muestras en tu post pero en SharePoint Online y no encuentro como :(

hay manera de implementar esta funcionalidad en SharePoint Online???

Te agradecería me confirmes.

Saludos

Él dijo...

Hola Francis.

Pues no lo he hecho nunca pero no debería haber ningún impedimento en que lo hagas en Office365. Todos los pasos que detallo son con la interfaz o con SharePoint designer, con lo que el procedimiento es básicamente el mismo. ¿Qué punto te está dando problemas?

Un saludo