[Xojo 2025r1] Como crear un tablero Kanban Web con soporte de Arrastrar y Soltar

A continuación encontrarás traducido al Castellano el artículo escrito por Ricardo Cruz y publicado originalmente en el Blog oficial de Xojo.

Imagina contar con un tablero Kanban interactivo justo en tu navegador: columnas “Pendiente”, “En Progreso” y “Completado”, cada una de ellas con las tarjetas que representan las tareas. Gracias al nuevo soporte de Arrastrar y Soltar de Xojo para los proyectos Web puedes seleccionar una tarjeta con el dispositivo apuntador, arrastrarla a otra columna y actualizar su estado, o incluso modificar el orden de las tarjetas en cada columna para priorizar las tareas.

El resultado final

El ejemplo de Arrastrar y Soltar ofrece una UI funcional con aspecto profesional y que resulta intuitivo; todo ello sin tener que escribir una sola línea de JavaScript (aunque usaremos algo de CSS para mejorar su aspecto).

Ten en cuenta, no obstante, que este es un proyecto de ejemplo creado para explorar la característica de Arrastrar y Soltar, y que no se trata de un tablero Kanban con toda la funcionalidad. Omitiré a propósito aspectos como la persistencia de los datos. Puedes encontrar el proyecto completo en la sección Examples del IDE, bajo Platforms > Web.

Veamos todos los pasos necesarios para hacerlo posible.

Crear los componentes necesarios

En primer lugar hemos de definir los bloques de construcción para nuestro tablero Kanban. En Xojo, los WebContainer son perfectos a la hora de crear elementos de UI reutilizables. Esto es lo que crearemos:

KanbanCard

Se trata de un WebContainer que representa cada una de las tarjetas de tareas. Contará con una simple etiqueta para el nombre de cada tarea (por ejemplo, “Escribir la entrada del blog”) y, quizá, un borde coloreado o manejador para indicar que se trata de un elemento que puedes arrastrar. Añade una WebLabel para el texto y define sus propiedades en el Inspector para que sea distintivo visualmente.

KanbanCardContainer

Se trata de otro WebContainer que actuará como columna. Contendrá múltiples container KanbanCard y servirá tanto como la fuente de arrastrar (es decir, el origen de las tarjetas) y también como destino de la operación de soltar (donde se dejarán las tarjetas arrastradas). Incluye una WebLabel en la parte superior para el título de la columna (por ejemplo, “To Do”), y un área rectangular debajo de ella para albergar las tarjetas.

Página principal

Se trata de una WebPage para contener todo. Aquí es donde colocaremos nuestras columnas una al lado de otra. En el IDE de Xojo, arrastra un WebContainer en tu proyecto para la tarjeta (Card), otro para la Columna (Column), y define tres instancias del Container Column en la WebPage principal (“To Do”, “In Progress”, “Done”).

KanbanCard

Este componente será realmente sencillo de crear. Se trata básicamente de un WebRectangle con una WebLabel que utilizaremos para el Título (Title). Para que sea más sencillo actualizarla, he añadido la propiedad calculada Title que actualizará TitleLabel cuando sea necesario.

Para el WebRectangle de fondo utilizaremos el siguiente ColorGroup. Observa que Xojo ha añadido soporte para los colores Named (por nombre), y que se basan en el tema Bootstrap utilizado, soportando también el modo Oscuro:

Como puedes observar, los controles BackgroundRectangle y TitleLabel implementan el evento Opening. Este se utiliza simplemente para configurar el cursor del apuntador que se utilizará cuando está situado sobre el control:

Me.Style.Cursor = WebStyle.Cursors.Move

El contenedor propiamente dicho también implementa el evento Opening para hacer que este control se pueda arrastrar, utilizando para ello la siguiente línea de código:

AllowTextDrag(WebDragItem.DragActionTypes.Move)

Puede arrastrarse cualquier descendiente de la clase WebUIControl y, sí, eso también incluye a los controles personalizados creados con el SDK Web.

Para el enumerador de WebDragItem.DragActionTypes puedes utilizar cualquiera de estas opciones:

En este caso sólo permitiremos “Mover” (valor “Move”) una tarjeta de un lugar a otro.

Hay casos en los que tiene sentido soportar múltiples tipos para la acción de arrastrar. En el navegador de archivos de tu sistema operativo, cuando arrastras y sueltas archivos y carpetas, puedes cambiar ente Mover, Enlazar o Copiar utilizando diferentes combinaciones del teclado. En función del tipo de acción de arrastre, el elemento en cuestión se moverá, se creará un enlace simbólico o bien se copiará, respectivamente.

Por lo general sólo implementarás Mover o Copiar, pero recuerda que también es posible tener más (al coste de incrementar la curva de aprendizaje para los usuarios de tu aplicación).

Permitir la acción de arrastrar algo es el primero de los dos pasos necesarios. También necesitarás un lugar en el cual soltar los elementos arrastrados.

KanbanCardContainer

Este contenedor será más elaborado, aunque fácil de seguir. Veamos cómo funciona en tiempo de ejecución, con algunas anotaciones:

La WebLabel para el Título (Title) y el WebButton para añadir nuevas tarjetas se posicionan manualmente en el editor de diseño del IDE. Lo mismo ocurre con el WebRectangle invisible encargado de contener los items KanbanCard y el botón personalizado KanbanAddCard.

Pero en vez de situar nuestras tarjetas manualmente, sacaremos provecho de la capacidad del Navegador a la hora de hacer este trabajo por nosotros. Queremos añadirlas de forma dinámica durante la ejecución y dejar que el navegador las apile verticalmente, de forma automática. También queremos que el navegador muestre una barra de desplazamiento cuando las columnas contienen varias tarjetas.

Este es el código que utilizaremos para añadir un WebRectangle:

// Permite que el framework sepa que queremos que
// el navegador sitúe los items automáticamente
Me.LayoutType = LayoutTypes.Flex
 
// Este estilo asegurará que las tarjetas no se
// organicen horizontalmente por el navegador
Me.Style.Value("flex-direction") = "wrap"
 
// Si hay más tarjetas que el espacio disponible
// este estilo permitirá que el usuario
// desplace el contenido verticalmente 
Me.Style.Value("overflow") = "auto"

Añadamos algunos métodos para añadir o eliminar tarjetas en tiempo de ejecución.

  • AddCardWithTitle(title As String)
  • AddCardWithTitleAt(title As String, index As Integer)
  • RemoveCardAt

Mover Tarjetas entre columnas

Aquí es donde brilla el soporte de Arrastrar y Soltar de Xojo. Cada contenedor Card tiener que poder ser arrastrado, y cada contenedor Column ha de aceptar las tarjetas arrastradas. En Xojo:

  • Permitir que las Card se puedan arrastrar: abre KanbanListCard en el IDE e implementa el evento Opening.

Introduce este código:

AllowTextDrag(WebDragItem.DragActionTypes.Move)
  • Aceptar las tarjetas soltadas: abre KanbanCardContainer e implementa el evento Opening. Este es el código requerido para aceptar los elementos soltados:
AcceptTextDrop(WebDragItem.DragActionTypes.Move)
  • Eliminar de la fuente: para mover (y no copiar) la tarjeta, elimina la tarjeta arrastrada de su padre original una vez que la operación de soltar ha tenido éxito. Esto se lleva a cabo en el evento DragEnd de la Columna fuente.

Con esto puedes arrastrar una tarjeta desde “To Do” a “In Progres”, además de ofrecer una retroalimentación visual sobre la operación de arrastre de una columna a otra. Xojo se encarga de gestionarlo por ti, sin necesidad de utilizar JavaScript o manipular el DOM.

La parte difícil: reordenar las tarjetas

Reordenar las tarjetas en una misma columna, o bien soltar una tarjeta sobre otra columna en una posición concreta, puede resultar complejo. Es necesario detectar dónde se suelta la tarjeta entre las disponibles y ajustar sus posiciones. La característica Arrastrar y Soltar de Xojo no ordena los elementos de forma nativa, de modo que hemos de simularlo.

Como en todas las cosas, hay varias formas de lograrlo; exploremos algunas opciones.

Hay que lidiar con las coordenadas X/Y. Una vez que sueltas una tarjeta podrías ver dónde se ha soltado, comparar las coordenadas con las de otras tarjetas y modificar el orden en consecuencia. En los proyectos desktop y mobile esto puede resultar una solución válida. En los proyectos Web, lidiar con coordenadas específicas podría funcionar, pero existen soluciones más sencillas y precisas.

Una segunda opción podría ser lo suficientemente buena en la mayoría de los casos. Las tarjetas también podrían aceptar la operación de Soltar; de modo que si soltases una tarjeta sobre otra, sólo tendríamos que poner la tarjeta soltada en la posición que tenía aquella que la recibe, moviendo hacia abajo el resto. De esta forma no tendrías que lidiar con las coordenadas de pantalla o el tamaño de los controles. El resultado se basará en esta idea.

Ahora bien, ¿que´tendríamos que hacer para generar el margen entre tarjetas? Quizá puedas crear un container transparente que también acepte el soltado de tarjetas para simular dicho margen entre tarjetas.

Esto funcionaría bien y, honestamente, te recomiendo que lo pruebes. Es súper fácil de implementar y, simplemente, funcionará. Si no quieres explorar CSS, está bien.

Dos desventajas:

  • No tendrás animaciones.
  • Tendrás que duplicar la cantidad de controles en pantalla (puede impactar el rendimiento).

Sin embargo tomé otro camino. Utilizando algo de CSS puedes añadir y modificar los márgenes sobre la marcha… además de aplicar transiciones. En mi proyecto de ejemplo el margen entre las tarjetas se gestiona mediante el estilo CSS margin-top.

Y aquí es donde viene la ayuda del framework de Xojo. Para facilitar la aplicación de estilos, este añade una clase CSS al elemento arrastrado y también al elemento sobre el que se encuentra el dispositivo apuntador cuando se acepta la operación de soltar.

  • dragging – El elemento HTML arrastrado tendrá esta propiedad.
  • dragover – El elemento HTML que se encuentra bajo el elemento arrastrado.
Algunas clases CSS añadidas por el framerwork Xojo Web en tiempo de ejecución para ayudar en la aplicación de estilos durante la operación de Arrastrar y Soltar.

En este caso, la tarjeta “Bar” recibirá la clase CSS del arrastre, mientras que “Test #2” recibirá la clase CSS dragover mientras que la tarjeta “Bar” esta sobre ella.

He añadido algo de transparencia a los elementos en la clase de arrastrar. Como puedes ver en la captura de pantalla, la opacidad de la tarjeta “Bar” está configurada al 30%.

Para la clase dragover he añadido algunos márgenes y transiciones. Si estás arrastrando algo sobre una tarjeta, se incrementará el margen superior, simulando así que se está haciendo espacio para la tarjeta que estás a punto de soltar.

Este es el aspecto de la sección HTML Header en el proyecto de ejemplo. No es mucho código, pero utiliza algunos trucos avanzados de CSS:

Este enfoque mantiene las tarjetas apiladas y con capacidad de ser reordenadas. Se trata de “la parte difícil” no porque tengas que escribir una gran cantidad de código, sino porque has de pensar en una solución que no requiera de idas y venidas entre el navegador y el servidor. El sistema de eventos de Xojo hace que se pueda gestionar sin la necesidad de usar JavaScript, y con algo de CSS el resultado será genial.

Algunas mejoras CSS

En algunos casos estoy usando sombras y bordes redondeados utilizando las clases CSS de Bootstrap.

Como puedes ver, estoy usando rounded-2 para el radio del borde, y shadow-sm para añadir de forma sencilla una sombra a las tarjetas.

Puedes leer más sobre esto en la siguiente entrada del blog:

Introducing Named Color and CSS Classes in Xojo Web

También puedes ver el proyecto de ejemplo relacionado:

Conclusiones

Ha sido un experimento interesante para explorar la característica de Arrastrar y Soltar de Xojo Web. Prueba el proyecto de ejemplo y explorar cada uno de los controles para ver como se han creado. Te recomiendo encarecidamente que intentes crearlo desde cero (y que preguntes en el foro si te atascas con algo).

Estamos deseando saber el modo en el que tienes previsto implementar la característica de Arrastrar y Soltar en tus proyectos. No seas tímido y crea un hilo en el foro para mostrar lo que has creado… o aquello en lo que estés trabajando.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *