Implementando una progress bar en un web panel GeneXus
Hoy me encontré con un problema, que con GeneXus no tiene una solución fácil. En una aplicación full web con GeneXus 9.0, tengo un proceso que puede demorar varios minutos, y mientras el proceso corre en el servidor, no hay forma de que el usuario se entere de lo que está haciendo.
La versión original
En la versión original, lo que tenía era un web panel, que hacía un call a un procedimiento, y cuando el procedimiento terminaba, llamaba a otro web panel. Algo así:
Event 'Accion'
call(PProcesa)
call(HMuestraResultado)
EndEvent
El problema con esta arquitectura es que por más que ponga mensajes en el evento, no se van a mostrar hasta que haya terminado de procesar.
Arquitectura de la solución
La solución fue llamar al procedimiento usando el comando submit, con lo que el procedimiento queda ejecutándose, pero el control vuelve de inmediato al web panel.
El código queda entonces así:
Event 'Accion'
submit(PProcesa, '')
call(HMuestraProgreso)
EndEvent
Además, se implementaron dos procedimientos, uno que devuelve la cantidad a procesar y otro que devuelve la cantidad que fueron procesados hasta el momento.
El web panel MuestraProgreso, invoca a estos dos procedimientos en el evento Start, de forma de saber el porcentaje de avance, y muestra un mensaje "Procesados n de N". Este web panel hace un refresh automático cada 3 segundos, de forma de ir mostrando el progreso. Veamos el código.
Event Start
&Total = udp(PCantidadTotal)
&Procesados = udp(PCantidadProcesados)
if &Procesados >= &Total
call(HMuestraResultado)
else
Form.MetaEquiv.AddItem('refresh', '3')
tbkMensaje.Caption = 'Procesados ' + trim(str(&Procesados, 9, 0)) + ' de ' + trim(str(&Total, 9, 0)) + '.'
do 'Progress bar'
endif
EndEvent // Start
El refresh automático se hace colocando un tag HMTL en el cabezal de la página, en el código es la línea con:
Form.MetaEquiv.AddItem('refresh', '3')
Mostrando una barra de progreso
Para mostrar la barra de progreso (progress bar) se necesita un poco más de código HTML. Hay muchas formas de hacerlo, en este caso elegí usar una tabla con varias celdas que se van pintando de algún color a medida que avanza.
Sub 'Progress bar'
&pbDivisiones = 100
&pbAvance = round(&Procesados * &pbDivisiones / &Total, 0)
tbkProgressBar.Caption = '
&nbps; | ' endfor tbkProgressBar.Caption += '
EndSub // 'Progress bar'
El control tbkProgressBar es un text block que se encuentra en el web form del web panel, y que tiene la propiedad Format = HTML.
El resto de la subrutina se debería poder usar tal cual, sin hacerle modificaciones.
No hay comentarios:
Publicar un comentario