viernes, 22 de noviembre de 2013

Personalización de Alfresco Share IV - cómo añadir componentes

En nuestro webinar de personalización de Alfresco Share mostramos cómo eliminar e incluir nuevos custom actions, templates y componentes.

En esta entrada explicaremos como añadir componentes a una página de Alfresco Share.

¿Qué es una página?
Cuando hablamos de páginas en Share puede parecer obvio que nos referimos a un archivo HTML presentado al usuario a través de un navegador. No obstante, para incluir nuestro componente debemos ir más allá de eso y entender la forma particular en la que Share crea esas páginas a través del framework Surf.

Una página en Share es el resultado de un conjunto de tres archivos:
  1. La definición de la página
  2. Una plantilla (template) donde se definen las regiones que tendrá la página
  3. Una instancia de la plantilla (template-instance) donde se indica qué componente va en cada region

¿Qué es un componente?
Por lo general un componente está formado por un conjunto de subcomponentes que en última instancia están representandos por un webscript de presentación y un evaluador (opcional) que determinará si se muestra el componente en la página.

Los componentes son los que en suma forman cada página de Alfresco Share. Cada componente se situa en una región concreta, indicado en el template-instance.

Objetivo: añadir un componente a la página "document-details"

Nuestro objetivo es añadir una galería que contenga todas las imágenes que se vayan creando a través de la selección de los custom actions para imágenes que hemos creado previamente.

  • En Alfresco
    • Crearemos un webscript de datos
    • Registraremos el webscript
  • En Share
    • Crearemos un webscript de presentación
    • Copiaremos la página original para modificarla
    • Incluiremos una nueva región en el template
    • Incluiremos nuestro componente en el template instance dentro la nueva región
Alfresco
Crear webscript de datos
Del lado del repositorio de Alfresco crearemos un webscript que provea la lista de imágnenes que deben mostrarse en la galería de nuestro componente:

Definción: 
<webscript>
    <shortname>GetAssociatedImages</shortname>
    <description>Get associated images to another image</description>
    <url>/imageTool/associated-images?noderef={noderef}</url>
    <format default="json">argument</format>
    <authentication>user</authentication>
</webscript>

Controlador:
public class GetAssociatedImagesWebScript extends AbstractWebScript {

    protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) {

        Map<String, Object> model = new HashMap<String, Object>();
        String ref = req.getParameter("noderef");
        NodeRef nodeRef = new NodeRef(ref);
        validateRequiredParams("NodeRef is required", ref);

        List imageList = imageService.getAssociatedImages(nodeRef);
        String jsonResp = JacksonUtil.toJSON(imageList, false, true);

        if (jsonResp != null) {
            model.put("jsonResp", jsonResp);
        }

        return model;
    }
}


JSON (freemarker):
<#if jsonResp??>${jsonResp}<#else>[ ]</#if>

Registrar webscript de datos
Es necesario registrar el webscript en el contexto de Spring para que Alfresco tenga constancia de ello:

<beans>
    <bean id="abstractWebScript"
          class="co.losi.imageTool.webscript.AbstractWebScript"
          abstract="true"
          parent="webscript">
        <property name="serviceRegistry" ref="ServiceRegistry"/>
        <property name="imageService" ref="imageToolService"/>
    </bean>
    <bean id="webscript.module.imageTool.associated-images.get"
          class="co.losi.imageTool.webscript.GetAssociatedImagesWebScript"
          parent="abstractWebScript">
    </bean>
</beans> 

Share
Crear webscript de presentaciónDel lado de Share crearemos un webscript de presentación que con la información provista por el webscript de Alfresco mostrará la galería de imágenes asociadas a la imagen que se esté visualizando:

Definción: 
<webscript>
    <shortname>image-gallery</shortname>
    <description>Display an image gallery</description>
    <url>/imageTool/components/image-gallery</url>
</webscript>

Controlador:
<import resource="classpath:/alfresco/templates/org/alfresco/import/alfresco-util.js"/>

function main() {
    var nodeRef = AlfrescoUtil.param('nodeRef');
    var url = "/imageTool/associated-images?noderef=" + encodeURIComponent(nodeRef);
    var result = remote.connect("alfresco").get(url);

    if (result.status == 200) {
        var jsonObject = eval('(' + result + ')');
        model.imageList = jsonObject;

    } else {
        model.imageList = null;
    }
}

main();

HTML (freemarker):
<div id="imageToolGalleryDiv" class="document-details-panel folder-details-panel imageTool-gallery" xmlns="http://www.w3.org/1999/html">
    <h2 id="rendition-list-heading" class="thin dark">${msg("header")}</h2>
    <br/>
    <#if imageList??>
        <#list imageList as oneImage>
            <div style="float:left; padding-right:5px">
                <img src="/share/proxy/alfresco/api/node/workspace/SpacesStore/${oneImage.nodeRef.id}/content/thumbnails/imageGallery">
            </div>

        </#list>
    <#else>
        ${msg("no.images")}
    </#if>
</div>

Copiar página original
En anteriores secciones pudimos observar que añadir y eliminar custom actions era posible mediante un archivo de configuración. En este caso, para añadir un componente a una página existente en Alfresco debemos sobreescribir dicha página con nuestra vérsión modificada. Como en la mayoría de los casos, es conveniente copiar lo que ya existe en Alfresco y reutilizarlo, por tanto, haremos una copia de los tres archivos relacionados con la página "document-details" que encontraremos en share.war:
  • Template
    • <tomcat>/webapps/share/WEB-INF/classes/alfresco/templates/org/alfresco
  • Template Instance
    • <tomcat>/webapps/share/WEB-INF/classes/alfresco/site-data/template-instances
  • Page
    • <tomcat>/webapps/share/WEB-INF/classes/alfresco/site-data/pages

Incluir nueva región en el template
Queremos que la galería se muestre justo debajo de la imagen visualizada, por tanto crearemos una nueva región a continuación de la región "web-preview" a la que identificaremos como "image-gallery":

<#include "include/alfresco-template.ftl" />
<@templateHeader>
   <@script type="text/javascript" src="${url.context}/res/modules/documentlibrary/doclib-actions.js"></@script>
   <@link rel="stylesheet" type="text/css" href="${page.url.context}/res/components/document-details/document-details-panel.css" />
   <@templateHtmlEditorAssets />
</@>

<@templateBody>
   <div id="alf-hd">
      <@region id="header" scope="global"/>
      <@region id="title" scope="template"/>
      <@region id="navigation" scope="template"/>
   </div>
   <div id="bd">
      <@region id="actions-common" scope="template"/>
      <@region id="actions" scope="template"/>
      <@region id="node-header" scope="template"/>
      <div class="yui-gc">
         <div class="yui-u first">
            <#if (config.scoped['DocumentDetails']['document-details'].getChildValue('display-web-preview') == "true")>
               <@region id="web-preview" scope="template"/>
            </#if>
            <@region id="image-gallery" scope="template"/>
            <@region id="comments" scope="template"/>
         </div>
         <div class="yui-u">
            <@region id="document-actions" scope="template"/>
            <@region id="document-tags" scope="template"/>
            <@region id="document-links" scope="template"/>
            <@region id="document-metadata" scope="template"/>
            <@region id="document-sync" scope="template"/>
            <@region id="document-permissions" scope="template"/>
            <@region id="document-workflows" scope="template"/>
            <@region id="document-versions" scope="template"/>
            <@region id="document-publishing" scope="template"/>
            <#if imapServerEnabled>
               <@region id="document-attachments" scope="template"/>
            </#if>
         </div>
      </div>

      <@region id="html-upload" scope="template"/>
      <@region id="flash-upload" scope="template"/>
      <@region id="file-upload" scope="template"/>
   </div>
   <@region id="doclib-custom" scope="template"/>
</@>

<@templateFooter>
   <div id="alf-ft">
      <@region id="footer" scope="global"/>
   </div>
</@>
Incluir componente en el template instance
Recordemos que un componente es un última instancia un webscript. En nuestro componente vamos a llamar al webscript de presentación que creamos y lo incluiremos en dentro de la región "image-gallery":

<component>
   <region-id>image-gallery</region-id>
   <sub-components>
       <sub-component id="default">
           <evaluations>
               <evaluation>
                   <evaluators>
                       <evaluator type="imageTool.evaluator.imageType">
                           <params>
                               <nodeRef>{nodeRef}</nodeRef>
                           </params>
                       </evaluator>
                   </evaluators>
                   <url>/imageTool/components/image-gallery</url>
                   <properties>
                       <nodeRef>{nodeRef}</nodeRef>
                   </properties>
               </evaluation>
           </evaluations>
       </sub-component>
   </sub-components>
</component>

Para mostrar el nuevo compomente sólo mientras se visualizan archivos tipo imagen, crearemos en Share un evaluador "imageTool.evaluator.imageType" que determine si el mimetype del nodo visualizado corresponde a jpeg, gif o png.

Interacción entre Share y Alfresco
Para entender correctamente la interacción que existe entre Share y Alfresco, vamos a seguir la secuencia de eventos que se produce desde que la página "document-details" es solicitida hasta que se muestra en pantalla:



  1. El usuario accede desde Share a la página para visualizar una imagen. Share determina el template correspondiente y la instancia para construir la página. Componente a componente se van realizando las llamadas a los distintos webscripts de presentación.
  2. Cuando Share llega a nuestro componente de galería de imágenes, se ejecuta el webscript de presentación que realiza una llamada al webscript de datos situado en Alfresco.
  3. Alfresco ejecuta el webscript de datos y genera un json con la lista de imágenes que se deben mostrar en la galería.
  4. Alfresco responde a Share enviando el objeto json.
  5. El webscript de presentación en Share recoge los datos propocionados por Alfresco y genera el html que finalmente se mostrará como galería de imágenes
Cómo integrar nuestra personalización en Alfresco Share
A continuación se especifíca dónde debemos colocar nuestras páginas personalizadas y componentes:

Páginas personalizadas:
  • Templates
    • <tomcat>/shared/classes/alfresco/web-extension/templates
    • <tomcat>/webapps/share/WEB-INF/classes/alfresco/templates
  • Template Instances
    • <tomcat>/shared/classes/alfresco/web-extension/site-data/template-instances
    • <tomcat>/webapps/share/WEB-INF/classes/alfresco/site-data/template-instances
  • Pages
    • <tomcat>/shared/classes/alfresco/web-extension/site-data/pages
    • <tomcat>/webapps/share/WEB-INF/classes/alfresco/site-data/pages
Componentes:
  • Share
    • <tomcat>/shared/classes/alfresco/web-extension/site-webscripts/com/midominio/components
    • <tomcat>/webapps/share/WEB-INF/classes/alfresco/site-webscripts/com/midominio/components  
  • Alfresco (webscripts de datos)
    • <tomcat>/shared/classes/alfresco/web-extension/templates/webscripts/com/midominio
    • <tomcat>/webapps/alfresco/WEB-INF/classes/alfresco/templates/webscripts/com/midominio

Nunca hagas cambios directamente sobre los archivos desplegados en el servidor web. Recuerda que siempre puedes crear un AMP con tus archivos e instalar así tus cambios.

 

No hay comentarios:

Publicar un comentario