4 de octubre de 2019

:: CSS. Sustituir imagen por css

En alguna ocasión necesitamos cambiar una imagen por otra en nuestras maquetaciones web.

Existen distintas alternativas, pero una de ellas sería mediante el uso de CSS. 








Por ejemplo, en un portal Liferay 6.2 al añadir el componente: "Búsqueda de contenido web", el aspecto del buscador sería el siguiente:


Para adaptarlo al diseño del portal, podríamos aplicar los siguientes estilos css, en los que se incluye la sustitución de la imagen "de la lupa", por una más acorde a la línea general del diseño:

.portlet-journal-content-search input.lfr-search-keywords {
    height: 61px;
    line-height: 61px;
    padding: 0;
    width: 100%;
    border-color: #e0e5e8;
    text-indent: 10px;
}

.portlet-journal-content-search .lfr-search-button {
    position: relative;
    left: 0;
    width: 80% !important;
    padding-left: 115px;
    height: 61px;
    background: url(/netic360-theme/css/images/search-icon-big.png) scroll no-repeat center center white;
    cursor: pointer;
    background-color: #c30e2e;
    top: -5px;
    
    box-sizing:border-box;
    overflow:hidden;
}

Tras aplicar estos estilos el aspecto sería similar al siguiente:

30 de septiembre de 2019

:: Liferay. Servir ficheros .xml

En Liferay 6.2 podemos configurar los ficheros que nos servirá, en lugar de descargarlos. Por ejemplo, ante la necesidad de servir un fichero .xml sin que se lo descargue, podemos revisar la línea siguiente, presente en el fichero "portal-ext.properties":

mime.types.content.disposition.inline=flv,gif,jpg,pdf,png,wmv


En esta línea añadiremos el mimetype del fichero que necesitamos. De esta manera, la línea quedará como sigue:

mime.types.content.disposition.inline=flv,gif,jpg,pdf,png,wmv,xml


Será necesario reiniciar el servicio para que los cambios surtan efecto.

24 de septiembre de 2019

:: Tip CSS. Ser específico

Cuando realizamos por ejemplo un desarrollo web, necesitamos hacer uso de CSS (Cascading Style Sheets) y es posible que en muchas ocasiones hayamos utilizado reglas "abreviadas"; Si queremos cambiar el color de fondo de un elemento, podríamos utilizar el siguiente código:







background:red;

Esta versión abreviada, aunque nos ahorra tiempo, automáticamente se están definiendo estas otras propiedades:

background-color : red;
background-repeat : repeat;
background-origin : padding-box;
background-image : none;
background-position : 0% 0%;
background-size : auto auto;
background-clip : border-box;
background-attachment : scroll;

Por lo tanto, la mejor opción sería ser lo más específico posible, en este caso:

background-color:red;

18 de septiembre de 2019

:: Tip CSS. Regla para marcar lo que ocupa un elemento

Únicamente como un detalle para marcar lo que ocupa un elemento cuando estamos maquetando, podríamos aplicarle los estilos css siguientes.
De esta manera, nos ayudará a darnos cuenta de lo que realmente está sucediendo en nuestra maqueta.





outline: 2px dotted red

10 de septiembre de 2019

:: Velocity. Obtener la fecha y hora actual

Para obtener la fecha y hora actual en una plantilla Velocity, por ejemplo para mostrar el año de Copyright en un portal Liferay, el código es el mostrado a continuación:

## Obtener fecha actual
#set ($fecha = $dateUtil)
#set ($fechaActual = $fecha.getCurrentDate())
#set ($anioActual = $fecha.getCurrentDate("yyyy", $locale))

Para mostrar el año actual, el marcado sería:
<div id="pie">
Todos los derechos reservados © $anioActual
</div>

6 de septiembre de 2019

:: Tip Alfresco. Aumentar el tiempo de sesión

En el caso de que necesitemos modificar el tiempo de sesión en Alfresco, esta tarea se realiza a nivel de: Tomcat, Alfresco y Share.

La línea a añadir es la siguiente:
<session-timeout>20</session-timeout>

Los ficheros a modificar son los siguientes:
<alfresco_home>/tomcat/conf/web.xml
<alfresco_home>/tomcat/webapps/alfresco/WEB-INF/web.xml
<alfresco_home>/tomcat/webapps/share/WEB-INF/web.xml
</alfresco_home></alfresco_home></alfresco_home>

Más información: https://community.alfresco.com/thread/205313-cambiar-tiempo-sesi%C3%B3n

3 de septiembre de 2019

:: Liferay. PermissionChecker not initialized

Un error que se producía en un portlet desarrollado en Liferay 6.2, a la hora de consultar un campo personalizado, era el siguiente: "PermissionChecker not initialized"


com.liferay.portal.kernel.messaging.MessageListenerException: java.lang.RuntimeException: com.liferay.portal.security.auth.PrincipalException: PermissionChecker not initialized
        at com.liferay.portal.kernel.scheduler.messaging.SchedulerEventMessageListenerWrapper.receive(SchedulerEventMessageListenerWrapper.java:86)
        at com.liferay.portal.kernel.messaging.InvokerMessageListener.receive(InvokerMessageListener.java:72)
        at com.liferay.portal.kernel.messaging.ParallelDestination$1.run(ParallelDestination.java:71)
        at com.liferay.portal.kernel.concurrent.ThreadPoolExecutor$WorkerTask._runTask(ThreadPoolExecutor.java:682)
        at com.liferay.portal.kernel.concurrent.ThreadPoolExecutor$WorkerTask.run(ThreadPoolExecutor.java:593)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.RuntimeException: com.liferay.portal.security.auth.PrincipalException: PermissionChecker not initialized
        at com.liferay.portlet.expando.model.impl.ExpandoBridgeImpl.getAttribute(ExpandoBridgeImpl.java:219)
        at com.liferay.portlet.expando.model.impl.ExpandoBridgeImpl.getAttribute(ExpandoBridgeImpl.java:199)
        at sun.reflect.GeneratedMethodAccessor6456.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.liferay.portal.kernel.bean.ClassLoaderBeanHandler.invoke(ClassLoaderBeanHandler.java:67)
        at com.sun.proxy.$Proxy1399.receive(Unknown Source)
        at com.liferay.portal.kernel.scheduler.messaging.SchedulerEventMessageListenerWrapper.receive(SchedulerEventMessageListenerWrapper.java:77)
        ... 5 more
Caused by: com.liferay.portal.security.auth.PrincipalException: PermissionChecker not initialized
        at com.liferay.portal.service.BaseServiceImpl.getPermissionChecker(BaseServiceImpl.java:82)
        at com.liferay.portlet.expando.service.impl.ExpandoValueServiceImpl.getData(ExpandoValueServiceImpl.java:125)
        at sun.reflect.GeneratedMethodAccessor1874.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:115)
        at com.liferay.portal.spring.transaction.DefaultTransactionExecutor.execute(DefaultTransactionExecutor.java:62)
        at com.liferay.portal.spring.transaction.TransactionInterceptor.invoke(TransactionInterceptor.java:51)
        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:111)
        at com.liferay.portal.spring.aop.ChainableMethodAdvice.invoke(ChainableMethodAdvice.java:56)
        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:111)
        at com.liferay.portal.spring.aop.ChainableMethodAdvice.invoke(ChainableMethodAdvice.java:56)
        at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:111)
        at com.liferay.portal.spring.aop.ServiceBeanAopProxy.invoke(ServiceBeanAopProxy.java:175)
        at com.sun.proxy.$Proxy228.getData(Unknown Source)
        at com.liferay.portlet.expando.service.ExpandoValueServiceUtil.getData(ExpandoValueServiceUtil.java:107)
        at com.liferay.portlet.expando.model.impl.ExpandoBridgeImpl.getAttribute(ExpandoBridgeImpl.java:208)
        ... 14 more


Este error se lanzaba a la hora de consultar el valor del campo personalizado desde una tarea programada:

user.getExpandoBridge().getAttribute("nombre-del-campo-personalizado");


La solución a este problema, documentado en los foros de Liferay fue el siguiente:

try{
//Backup del permiso actual
PermissionChecker permissionCheckerBackup= PermissionThreadLocal.getPermissionChecker();

//Recupera el valor del del campo personalizado
PrincipalThreadLocal.setName(user.getUserId());
PermissionChecker permissionChecker;
permissionChecker = PermissionCheckerFactoryUtil.create(user);
PermissionThreadLocal.setPermissionChecker(permissionChecker);

campoPersonalizado=(boolean) user.getExpandoBridge().getAttribute("nombre-del-campo-personalizado");

//Restablece el permiso inicial
PermissionThreadLocal.setPermissionChecker(permissionCheckerBackup);
}catch(Exception ex){
ex.printStackTrace();
}


Más información: https://liferay.dev/forums/-/message_boards/message/48763277

:: Liferay DXP 2026. Habilitar RSS

En la versión Liferay DXP 2026 para habilitar las fuentes de datos RSS debemos seguir los pasos siguientes: 1.- Accederemos a la Configuraci...