Ya estamos terminando nuestro portlet para Liferay que nos ayudará a aprender y gestionar tareas Por si no recordáis o acabáis de llegar a este post aquí os dejo un par de links a la parte 1 y a la parte 2 respectivamente.
Vamos a poner de nuevo como quedará el portlet porque hoy viene una de las partes más importantes, la vista:

Llegados aquí ya tenemos el Service Builder montado, si recordáis con solo definir un par de entidades con sus columnas correspondientes en el archivo services.xml y pulsar sobre la tarea (ant) “build Services” creamos un montón de código que nos sirve para mapear la base de datos. En el anterior post vimos cómo crear los controladores, en este ya tenemos el final. Vamos a definir 5 archivos JSP donde programaremos todos los elementos gráficos.
Creando el init
Así que lo primero para tener bien organizado el código será crear una carpeta llamada “JSP” (imaginación al poder) en docroot.
En Este nuevo directorio “/docroot/jsp” creamos el primer archivo llamado init.jsp Este primer archivo no tiene nada de vista, solo todas las importaciones de taglib, lo hacemos así para no repetir el mismo código de importaciones en todas las clases. También hemos definido 3 variables que nos ayudaran a no repetir código.
Brown-tsk-portlet/docroot/jsp/init.jsp
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<%@ page import="com.liferay.portal.kernel.util.StringUtil" %>
<%@ page import="com.liferay.portal.security.permission.PermissionChecker" %>
<portlet:defineObjects />
<liferay-theme:defineObjects />
<%
long groupId = themeDisplay.getPortletGroupId();
String name = themeDisplay.getPortletDisplay().getRootPortletId();
String primKey = themeDisplay.getPortletDisplay().getResourcePK();
%>
Vamos a por el archivo principal, llamado view.jsp
La vista general
Si nos fijamos en la figura de arriba tenemos botones (addlist y additem), justo debajo la barra de pestañas (tabs) con cada una de las listas con una señalada por defecto SIEMPRE y debajo las tareas de esa lista. Pues todo ello puede resumirse en este archivo:
<%@ include file="init.jsp" %>
<portlet:renderURL var='urlAddList'><portlet:param name='action' value='addList'/><portlet:param name='order' value='${order}'/><portlet:param name='list' value='${list}'/></portlet:renderURL>
<portlet:renderURL var='urlEditList'><portlet:param name='action' value='addList'/><portlet:param name='order' value='${order}'/><portlet:param name='list' value='${list}'/><portlet:param name='id' value='${list}'/></portlet:renderURL>
<portlet:renderURL var='urlAddItem'><portlet:param name='action' value='addItem'/><portlet:param name='order' value='${order}'/><portlet:param name='list' value='${list}'/></portlet:renderURL>
<portlet:renderURL var='def'><portlet:param name='action' value='view'/></portlet:renderURL>
<p>
<aui:button name='addList' value='add-list' onclick='<%=renderResponse.getNamespace()+"toAddList()" %>' />
<c:if test="${list!=null}">
<aui:button name='addItem' value='add-item' onclick='<%=renderResponse.getNamespace()+"toAddItem()" %>' />
</c:if>
</p>
<liferay-ui:tabs
names="${formNames}"
value="${formTab}"
url='<%=def %>'
refresh="<%= true %>"
/>
<p style='text-align: right;'>
<c:if test="${list!=null}">
<liferay-ui:icon
cssClass="top-link"
image="edit"
label="<%= true %>"
message="editlist"
url='${urlEditList}'
/>
</c:if>
</p>
<aui:script>
function <%=renderResponse.getNamespace() %>toAddList() {
window.location.href='<%=urlAddList %>';
}
function <%=renderResponse.getNamespace() %>toAddItem() {
window.location.href='<%=urlAddItem %>';
}
</aui:script>
<table style='width: 100%;'>
<tr class="portlet-section-header results-header">
<td>
<b>
<a style='text-decoration: none;' href='<portlet:renderURL>
<portlet:param name='action' value='view'/>
<portlet:param name='list' value='${list}'/>
<portlet:param name='order' value='label'/>
</portlet:renderURL>'>
<liferay-ui:message key="label" />
<c:if test="${order=='label'}">
∨
</c:if>
</a>
</b>
</td>
<td>
<b>
<a style='text-decoration: none;' href='<portlet:renderURL>
<portlet:param name='action' value='view'/>
<portlet:param name='list' value='${list}'/>
<portlet:param name='order' value='weight'/>
</portlet:renderURL>'>
<liferay-ui:message key="weight" />
<c:if test="${order=='weight'}">
∨
</c:if>
</a>
</b>
</td>
<td>
<b>
<a style='text-decoration: none;' href='<portlet:renderURL>
<portlet:param name='action' value='view'/>
<portlet:param name='list' value='${list}'/>
<portlet:param name='order' value='status'/>
</portlet:renderURL>'>
<liferay-ui:message key="status" />
<c:if test="${order=='status'}">
∨
</c:if>
</a>
</b>
</td>
</tr>
<c:forEach var="item" items="${itemList}">
<portlet:renderURL var='urlViewItem'>
<portlet:param name='list' value='${list}'/>
<portlet:param name='itemid' value='${item.id}'/>
<portlet:param name='order' value='${order}'/>
</portlet:renderURL>
<tr>
<td>
<aui:a href='${urlViewItem}'>
${item.label}
</aui:a>
</td>
<td>
<c:choose>
<c:when test="${item.weight>=16}">
<spanclass='weight_highest'>
</c:when>
<c:when test="${item.weight>=4}">
<spanclass='weight_high'>
</c:when>
<c:when test="${item.weight>=-4}">
<spanclass='weight_normal'>
</c:when>
<c:when test="${item.weight>=-14}">
<spanclass='weight_low'>
</c:when>
<c:otherwise>
<spanclass='weight_lowest'>
</c:otherwise>
</c:choose>
${item.weight}</span>
</td>
<td>
<c:choose>
<c:when test="${item.status==0}">
<span class='status_normal'><liferay-ui:message key="normal" /></span>
</c:when>
<c:when test="${item.status==1}">
<span class='status_waiting'><liferay-ui:message key="waiting" /></span>
</c:when>
<c:when test="${item.status==2}">
<span class='status_cancelled'><liferay-ui:message key="cancelled" /></span>
</c:when>
<c:when test="${item.status==3}">
<span class='status_finished'><liferay-ui:message key="finished" /></span>
</c:when>
<c:otherwise>
${item.status}
</c:otherwise>
</c:choose>
</td>
</tr>
</c:forEach>
</table>
Si veis al principio del archivo tenemos un include para evitar realizar allí todas las importaciones que realizamos en init.jsp
Viendo solo un ítem
SI hacemos clic encima de una tarea podemos ver con más detalle dicha tarea, más o menos veremos algo así:

El código que genera esta vista es algo así:
<%@ include file="init.jsp" %>
<portlet:renderURL var='urlCancel'><portlet:param name='action' value='view'/><portlet:param name='order' value='${order}'/><portlet:param name='list' value='${list}'/></portlet:renderURL>
<liferay-ui:header title="${listObj.description} - ${item.label}" backURL="${urlCancel}" />
4px;" >
'urlEditItem'>
'action' value='addItem'/>
'list' value='${list}'/>
'itemid' value='${item.id}'/>
'order' value='${order}'/>
"top-link"
image="edit"
label=""
message="edit"
url='${urlEditItem}'
/>
<aui:field-wrapper label="description">
<% pageContext.setAttribute("newLineChar", "\n"); %>
${fn:replace(item.description,newLineChar,"<br/>")}
</aui:field-wrapper>
left; margin-right: 4px;" >
"label">
'${item.label}' />
left; margin-right: 4px;" >
"status">
"${statuses[ item.status ]=='Normal'}">
'status_normal'>"normal" />
"${statuses[ item.status ]=='Waiting for'}">
'status_waiting'>"waiting" />
"${statuses[ item.status ]=='Cancelled'}">
'status_cancelled'>"cancelled" />
"${statuses[ item.status ]=='Finished'}">
'status_finished'>"finished" />
both; overflow: hidden; height: 1px;" >
Añadiendo una lista de tareas
Cuando pulsamos desde la pantalla principal de nuestro portlet de gestión de tareas el botón de añadir una lista de tareas no aparece algo como esto:

Como veis tenemos una caja donde añadir el nombre de la lista de tarea y un peso que nos servirá para ordenar las listas en la barra de pestañas.
<%@ include file="init.jsp" %>
<portlet:actionURL var='actionAddList'><portlet:param name='action' value='addList'/><portlet:param name='order' value='${order}'/></portlet:actionURL>
<portlet:renderURL var='urlCancel'><portlet:param name='action' value='view'/><portlet:param name='order' value='${order}'/><portlet:param name='list' value='${list}'/></portlet:renderURL>
<portlet:actionURL var='actionDeleteList'>
<portlet:param name='action' value='addList'/>
<portlet:param name='delete' value='1'/>
<portlet:param name='id' value='${item.id}'/>
<portlet:param name='order' value='${order}'/>
</portlet:actionURL>
<liferay-ui:header title="list-title" backURL="${urlCancel}" />
<form method="post" action="<%= actionAddList %>" onSubmit = "<%= "javascript: return "+renderResponse.getNamespace()+"validate(this);" %>" >
left; margin-right: 4px; height: 43px;" >
'text' name='description' label="list-name" value='${item.description}' />
left; margin-right: 4px; height: 43px;" >
"weight" name="weight">
"${item.weight}" var="sval"/>
"${item.id==null}">
"0" var="sval"/>
"i" begin="0" end="10">
"${i-5}" selected="${sval==i-5}">${i-5}
both; overflow: hidden; height: 1px;" >
<p>
</p>
<p>
<c:if test="${item.id!=null}">
<aui:input type='hidden' name='id' value='${item.id}' />
<input type='submit' value='<liferay-ui:message key="save" />'/>
<input type='button' onclick='<%=renderResponse.getNamespace()+"toDelete();" %>' value='<liferay-ui:message key="action.DELETE" />'/>
</c:if>
<c:if test="${item.id==null}">
<aui:input type='hidden' name='id' value='-1' />
<input type='submit' value='<liferay-ui:message key="add" />'/>
</c:if>
<input type='button' onclick="javascript: window.location.href='${urlCancel}';" value='<liferay-ui:message key="cancel" />'/>
</p>
</form>
<aui:script use="aui-node">
<portlet:namespace />validate=function() {
if ( AUI().one("#<portlet:namespace />description").val().trim()=="" ) {
alert( '<liferay-ui:message key="this-field-is-mandatory" />' );
AUI().one("#<portlet:namespace />description").focus();
return false;
}
return true;
}
<portlet:namespace />toDelete=function() {
if ( confirm("<liferay-ui:message key="attention-delete" />") )
window.location.href='${actionDeleteList}';
}
</aui:script>
Añadiendo una nueva tarea
Cuando queremos añadir una nueva tarea tenemos algo como esto:

El código lo tenemos aquí:
<%@ include file="init.jsp" %>
<portlet:actionURL var='actionAddItem'>
<portlet:param name='order' value='${order}'/>
<portlet:param name='action' value='addItem'/>
</portlet:actionURL>
<portlet:actionURL var='actionDeleteItem'>
<portlet:param name='action' value='addItem'/>
<portlet:param name='delete' value='1'/>
<portlet:param name='id' value='${item.id}'/>
<portlet:param name='list' value='${list}'/>
<portlet:param name='order' value='${order}'/>
</portlet:actionURL>
<portlet:renderURL var='urlCancel'>
<portlet:param name='order' value='${order}'/>
<portlet:param name='action' value='view'/>
<portlet:param name='list' value='${list}'/>
</portlet:renderURL>
<liferay-ui:header title="item-title" backURL="${urlCancel}" />
<form method="post" action="<%= actionAddItem %>" onSubmit = "<%= "javascript: return "+renderResponse.getNamespace()+"validate(this);" %>" >
<aui:input type='hidden' name='list' value='${list}' />
left; margin-right: 4px;" >
'text' name='label' label="label" value='${item.label}' />
left; margin-right: 4px;" >
"weight" name="weight" style="float: left;">
"${item.weight}" var="sval"/>
"${item.id==null}">
"0" var="sval"/>
"i" begin="0" end="10">
"${i-5}" selected="${sval==i-5}">${i-5}
left; margin-right: 4px;" >
"status" name="status" style="float: left;">
"0" label="normal" selected="${item.status==0}" />
"1" label="waiting" selected="${item.status==1}" />
"2" label="cancelled" selected="${item.status==2}" />
"3" label="finished" selected="${item.status==3}" />
both; overflow: hidden; height: 1px;" >
<aui:input type='textarea' name='description' label="item-description" value='${item.description}' style="width: 100%;" />
<p>
</p>
<p>
<c:if test="${item.id!=null}">
<aui:input type='hidden' name='id' value='${item.id}' />
<input type='submit' value="<liferay-ui:message key='save' />"/>
<input type='button' onclick='<%=renderResponse.getNamespace()+"toDelete();" %>' value='<liferay-ui:message key="action.DELETE" />'/>
</c:if>
<c:if test="${item.id==null}">
<aui:input type='hidden' name='id' value='-1' />
<input type='submit' value='<liferay-ui:message key="add" />'/>
</c:if>
<input type='button' onclick="javascript: window.location.href='${urlCancel}';" value='<liferay-ui:message key="cancel" />'/>
</p>
</form>
<aui:script>
<portlet:namespace />validate=function() {
if ( AUI().one("#<portlet:namespace />label").val().trim()=="" ) {
alert( '<liferay-ui:message key="this-field-is-mandatory" />' );
AUI().one("#<portlet:namespace />label").focus();
return false;
}
return true;
}
<portlet:namespace />toDelete=function() {
if ( confirm("<liferay-ui:message key="attention-delete" />") )
window.location.href='<%=actionDeleteItem %>';
}
</aui:script>
Ya hemos como crear la vista, para tener un portlet totalmente funcional deberemos poder probarlo y para ello es necesario configurarlo.
Configurando el portlet
Por ultimo solo nos queda configurar un poco los parámetros del portlet para que eche a andar.
Modificamos la categoría
Para que a la hora de añadir el portlet podamos encontrarlo fácilmente vamos a definirle una categoría propia de la siguiente manera.
Abrimos el archivo Liferay-display.xml y modificamos la categoría, yo le he puesto como categoría “Demos JesusLC SB”

Modificando el Controller
Para que el portlet de gestión de tareas funcione, debemos indicarle cual es nuestra clase controladora, la que implementa a MVCPortlet, si os acordáis del post anterior creamos una clase llamada BalancerController, pues en el archivo portlet.xml debemos poner la ruta de esa clase, además de indicar que tenemos un archivo llamado Language.properties donde está definido el idioma del portlet.
Debe quedar todo como esta figura:

Finalmente ya hemos terminado con este Portet, solo tenemos pulsar sobre build.xml y correr la tarea ant para que se añada al servidor y empezar a utilizarlo.







Replica a jesuslc Cancelar la respuesta