Image
Como ajustar y centrar una imagen en un videoframe
Como ajustar y centrar una imagen en un videoframe

Como ajustar y centrar una imagen en un videoframe. En este tutorial vamos a ver como ajustar y centrar una imagen subida por nosotros como poster al frame de un video.

Soluciones hay diversas, y cada maestrillo tiene su librillo, pero aquí voy a explicar la que me ha servido para hacer el ajuste.

Nos encontramos con la situación de que si el video es un video subido por nosotros, por defecto lo encontraremos como “display: none” hasta que se ejecute el play, y de ser un video de Youtube o Vimeo embebido en un iframe encontraremos que el iframe también está en “display: none” y además posicionado en absoluto. En ambos casos, si nos basamos en estos dos elementos como base, veremos que el contendor no tiene ni altura ni anchura, ya que ningún hijo se la está dando.

Image
Como ajustar y centrar una imagen en un videoframe

Para empezar con la solución lo primero es ir a modules/contrib/layoutcomponent/modules/lc_simple_video/templates donde encontraremos un twig con el siguiente código:

<div class="videoimage">
    {{ content.field_sv_image }}
    {#      {{ content|without('field_sv_video_type', 'field_sv_upload_video', 'field_sv_video') }}#}
    {% if content.field_sv_video_type['#items'][0].value == 'video_url' %}
        {{ content.field_sv_video }}
    {% else %}
        {{ content.field_sv_upload_video }}
    {% endif %}
</div>
Image
Como ajustar y centrar una imagen en un videoframe

 

Copiamos el archivo del twig y lo ponemos en la parte custom de nuestro tema. Así que iremos a themes/custom/nombre_del_proyecto/templates y lo pegamos ahí.

Como se dan dos situaciones de video, un video embebido de una url y un video subido por nosotros, lo vamos a separar en dos bloques diferentes ayudándonos de la variable que nos proporciona el twig, dejando un código de la siguiente manera:

<div class="videoimage">
    {#      {{ content|without('field_sv_video_type', 'field_sv_upload_video', 'field_sv_video') }}#}
    {% if content.field_sv_video_type['#items'][0].value == 'video_url' %}
    <div class="videoimage-url">
        {{ content.field_sv_image }}
      <div class="videoimage__video">
        {{ content.field_sv_video }}
      </div>
    </div>
    {% else %}
      <div class="videoimage-upload">
          {{ content.field_sv_image }}
          <div class="videoimage__video">
            {{ content.field_sv_upload_video }}
          </div>
      </div>
    {% endif %}
</div>
Image
Como ajustar y centrar una imagen en un videoframe

 

Con esto tenemos listo el twig, ahora vamos a hacer la magia en el CSS, bueno, en nuestro caso SCSS.

Para ello hay que tener clara una cosa, ya que la imagen va a ser posicionada y como  tanto el video como el iframe en ambos casos están a “display: none” o posicionados, ninguno de ellos genera altura en el contendor, por lo que la imagen no se verá.

En el caso de un video subido por nosotros, pondremos el video a “display: block”, esto generará la altura y anchura que debe de tener la caja. Ahora basta con posicionar la imagen y por encima, para ello nos aseguramos que todos los padres de la imagen tengan la altura y la anchura del contendor, que todo lo que sobresalga de ellos no se visualice y que cuando tengan la clase “hidden” desaparezcan.

Ahora, con la imagen subida, hacemos que la imagen tenga una anchura y altura adaptable pero que como mínimo siempre sea la del contendor y su máximo sea la que deba por defecto, con esto hecho la posicionamos en el medio.

En el caso de un video embebido de Youtube o Vimeo, como necesitamos que el contendor tenga una altura y que esta altura sea variable para que la maquetación sea líquida y que el responsive nos venga ya dado, no declararemos un height en el contendor, si no que usaremos un paddíng en porcentaje sabiendo el ratio entre el alto y el ancho de nuestro video. En nuestro caso el ratio en porcentaje de nuestro video es de 56.25%.

Una vez añadido este padding, nuestra caja ya tiene una altura, por lo que posicionar la imagen será igual que como con el vídeo subido, hacemos que los padres tengan un tamaño igual al contenedor, que se oculten si tienen la clase “hidden” y posicionamos la imagen de la misma manera.

El código SCSS resultante de todo esto quedaría así:

.videoimage{
  position: relative;
  &-upload{
    .field--name-field-sv-image{
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      z-index: 1;
      overflow: hidden;
      margin:0;
      .contextual-region,
      .field--name-field-media-image,
      .field__item{
        display: block;
        width: 100%;
        height: 100%;
        overflow: hidden;
        &.hidden{
          display: none;
        }
      }
      img{
        position: absolute;
        width: auto;
        height: auto;
        min-height: 100%;
        min-width: 100%;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        max-height: initial!important;
      }
    }
    .videoimage__video{
      video{
        display: block!important;
      }
    }
  }
  &-url{
    .field--name-field-sv-image {
      margin: 0;
      padding-top: 56.25%;
      overflow: hidden;
      .contextual-region,
      .field--name-field-media-image,
      .field__item{
        display: block;
        width: 100%;
        height: 100%;
        overflow: hidden;
        &.hidden{
          display: none;
        }
      }
      .contextual-region{
        position: absolute;
        top: 0;
        left: 0;
      }
      img{
        position: absolute;
        width: auto;
        height: auto;
        min-height: 100%;
        min-width: 100%;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        max-height: initial!important;
      }
    }
  }
}
Image
Como ajustar y centrar una imagen en un videoframe
Image
Como ajustar y centrar una imagen en un videoframe

 En caso de trabajar directamente en CSS el código sería:

.videoimage {
  position: relative;
}
.videoimage-upload .field--name-field-sv-image {
  position: absolute;
top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  overflow: hidden;
  margin: 0;
}
.videoimage-upload .field--name-field-sv-image .contextual-region,
.videoimage-upload .field--name-field-sv-image .field--name-field-media-image,
.videoimage-upload .field--name-field-sv-image .field__item {
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.videoimage-upload .field--name-field-sv-image .contextual-region.hidden,
.videoimage-upload .field--name-field-sv-image .field--name-field-media-image.hidden,
.videoimage-upload .field--name-field-sv-image .field__item.hidden {
  display: none;
}
.videoimage-upload .field--name-field-sv-image img {
  position: absolute;
  width: auto;
  height: auto;
  min-height: 100%;
  min-width: 100%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  max-height: initial !important;
}
.videoimage-upload .videoimage__video video {
  display: block !important;
}
.videoimage-url .field--name-field-sv-image {
  margin: 0;
  padding-top: 56.25%;
  overflow: hidden;
}
.videoimage-url .field--name-field-sv-image .contextual-region,
.videoimage-url .field--name-field-sv-image .field--name-field-media-image,
.videoimage-url .field--name-field-sv-image .field__item {
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.videoimage-url .field--name-field-sv-image .contextual-region.hidden,
.videoimage-url .field--name-field-sv-image .field--name-field-media-image.hidden,
.videoimage-url .field--name-field-sv-image .field__item.hidden {
  display: none;
}
.videoimage-url .field--name-field-sv-image .contextual-region {
  position: absolute;
  top: 0;
  left: 0;
}
.videoimage-url .field--name-field-sv-image img {
  position: absolute;
  width: auto;
  height: auto;
  min-height: 100%;
  min-width: 100%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  max-height: initial !important;
}

Y esto ha sido como ajustar y centrar una imagen a un frame de video, recordad que tenéis este y otros manuales de ayuda en el blog y si aun así no halláis respuesta a vuestro problema, podéis publicar vuestras preguntas en el tablón, donde la comunidad os ayudará a resolverlas.

 

Esto ha sido:  Como ajustar y centrar una imagen en un videoframe.

Image
Mostrar datos externos (API) mediante vistas de Drupal
Mostrar datos externos (API) mediante vistas de Drupal

Mostrar datos externos (API) mediante vistas de Drupal, tenemos la necesidad de mostrar datos procedentes de la respuesta de una API en nuestro Drupal. Para ello utilizaremos las vistas de Drupal mostrando estos datos como si pertenecieran al propio Drupal con las ventajas de utilizar vistas. Para ello crearemos una “tabla” ficticia con sus respectivos campos dónde pasaremos los datos procedentes de la respuesta de la API.

El primer paso es crear esta “tabla” ficticia con los campos dónde mostraremos los datos. Mediante el hook views data defininos lo que sería nuestra tabla y posteriormente los campos.

Image
Mostrar datos externos (API) mediante vistas de Drupal

 

Una vez definidos estos datos tenemos que crearnos nuestro plugin para mostrar estos datos en la vista. Para ello nos crearemos nuestro query plugin inyectando el contenedor de nuestra clase para consumir los datos de la API.

Image
Mostrar datos externos (API) mediante vistas de Drupal

 

Una vez que tengamos definido el Query plugin, podemos pasarle nuestros datos a los campos a través de la función execute. Realizamos la llamada a la API y almacenamos la respuesta. Ahora vamos añadiendo cada fila de datos devuelta por la API a la vista.

 

Image
Mostrar datos externos (API) mediante vistas de Drupal

 

Una vez hecho todo esto proceso, cuando vamos a crear una vista mediante la administración. En el selector para seleccionar que queremos mostrar, vemos nuestra “tabla”.

Image
Mostrar datos externos (API) mediante vistas de Drupal

 

Una vez en la vista, podemos seleccionar el tipo tabla para visualizar los datos mostrando campos. Al añadir campos, veremos todos los campos definidos previamente.

Image
Mostrar datos externos (API) mediante vistas de Drupal

Y esto ha sido Mostrar datos externos (API) mediante vistas de Drupal, recordad que tenéis este y otros manuales de ayuda en el blog y si aun así no halláis respuesta a vuestro problema, podéis publicar vuestras preguntas en el tablón, donde la comunidad os ayudará a resolverlas.

 

Image
Crear una tabla de bbdd en la instalación de un módulo en Drupal
Crear una tabla de bbdd en la instalación de un módulo en Drupal

En el desarrollo de un módulo en Drupal, una de las cosas que más nos puede interesar es, que en la instalación de nuestro módulo, se pueda generar una tabla donde nuestra aplicación pueda tratar datos.

Sobre la relación de Drupal y las bases de datos

Drupal utiliza un sistema que permite llevar a cabo dicha operación independientemente del motor de base de datos con el que esté trabajando llamado Database Abstraction Layer que traduce el lenguaje de Drupal para el tratamiento de las bases de datos al lenguaje del motor de base de datos. De modo que cualquier operación que desarrollemos con base de datos en Drupal, podrá funcionar en cualquier motor de base de datos en el que instalemos Drupal.

Entendamos motor de base de datos como sistema que tengamos instalado en el servidor, como MariaDB, MySQL, PotgreSQL, etc.

Suponiendo que tenemos creado un primer módulo, en caso contrario podéis encontrar un interesante tutorial con los primeros pasos a seguir en este mismo portal, tenemos que tener en cuenta que podemos, en la instalación del módulo, incluir un fichero de instalación que establezca los primeros pasos para la implantación del módulo y entre ellos el de la creación de nuestras tablas en bases de datos.

Pasos previos a la creación del módulo

Recordemos que los ficheros de nuestro módulo tiene que estar en una carpeta del mismo nombre dentro de la carpeta custom de la carpeta modules.

/var/www/html/midrupal/web/modules/custom/misdatos

En dicha carpeta tenemos creado el fichero misdatos.info.yml, en el cual introducimos los damos básicos que Drupal necesita para saber qué características tiene el módulo como el nombre, el tipo, una descripción, etc. A continuación vemos los datos que yo he introducido.

name: Mis datos
type: module
description: 'Modulo de base de datos'
package: Mis modulos
core_version_requirement: ^9

Excepto package que no lo es pero permite tener organizado nuestro módulo en grupos, el resto son datos obligatorios.

Ahora entre todos los módulos podemos encontrar el nuestro en un grupo llamado “Mis módulos”.

Sería la información mínima, pero podemos ampliarlo poniendo la versión del módulo.

version: 1.0

Ocultar el módulo a miradas indiscretas con el parámetro hidden, de modo que no aparecerá en el listado de módulos.

hidden: TRUE

También podemos indicar una ruta de la página de configuración del módulo, para lo cual tendríamos que poner el nombre de sistema de la ruta de dicha página.

configure: misdatos.admin

Puedes encontrar información completa sobre la configuración del fichero info en el enlace https://www.drupal.org/node/2000204

El módulo en ese estado, podemos activarlo pero no va a hacer nada aún. Realmente, Drupal sabe que existe pero nada más.

Durante la instalación del módulo

Para que módulo haga algo en la instalación tenemos que incluir un fichero llamado misdatos.install. Dicho fichero es un script de php que contiene una función hook_install()

Para los que no lo sepan, un hook o gancho es una función que llama a una función preestablecida que busca Drupal en su ejecución, y si existe, ejecuta sus instrucción. Veamos cómo funciona.

Para hacer funcionar el hook_install(), tenemos que cambiarle el nombre y  sustituir hook por el nombre de nuestro módulo de modo que la función se llamaría misdatos_install().

Lo primero que tener ya escrito en nuestro fichero es:

<?php

function misdatos_install(){

}

Es conveniente al programar en Drupal acostumbrarse a seguir las buenas prácticas establecidas por la comunidad, y una cosa que se ha establecido, ha sido la de documentar correctamente lo que se programa. De modo que en este caso tenemos que introducir un comentario en la parte superior del fichero con la siguiente estructura.

/**
*@file
*Descripción de la función del script en inglés
*/

@file, es una directiva que describe la función del fichero y que afecta a la documentación automática de Drupal. Bueno, es un tema para hablar mucho pero no es que no trae aquí de momento.

Nuestro fichero tiene ahora este aspecto.

<?php

/**
*@file
*Descripción de la función del script en inglés
*/

function misdatos_install(){

}

El siguiente paso es llamar del mismo modo a la función gancho, o hook que permite la creación de tablas y este se llama hook_schema(). Igual que antes, modificamos el nombre por misdatos_schema().

Tenemos que tener en cuenta que para que el hook_install pueda trabajar correctamente con la tabla que creemos, esta tiene que estar generada antes de que se ejecute la instalación, por ello tenemos que poner la función que crea las tablas antes de todo.
 

<?php

/**
*@file
*Descripción de la función del script en inglés
*/

function misdatos_schema(){

}

function misdatos_install(){

}

Encima de cada función ponemos la misma estructura de comentario pero sin la directiva @file.

<?php

/**
 *@file
 *Descripción de la función del script en inglés
 */

/**
 *  Descripción de la función en inglés
 */
function misdatos_schema(){

}

/**
 *  Descripción de la función en inglés
 */
function misdatos_install(){

}

En la función esquema podemos crear las tablas que necesitemos. Lo que tenemos que crear dentro de la función misdatos_schema() es un array $schema[]. Cada campo del array tiene el nombre de la tabla que creemos $schema[‘tabla_uno’]. Dentro de cada campo introducimos una array que contiene las características de cada campo de la tabla. Veamos un ejemplo:

$schema[‘tabla_uno’] = [
  ‘description’ => ‘Cadena de texto que describe la tabla’,
  ‘fields’ => [ // Estructura de campos que define una tabla
  ],
  'primary key' => [ // Indica los campos que son clave primaria de la tabla ],
  ‘indexes’ => [ // array que contiene los indices de la tabla ],
];

Es conveniente tener algo de idea respecto al funcionamiento de las bases de datos.

El campo fields, almacena un array con la estructura de campos de la tabla. Podemos poner un ejemplo del módulo book.
 

$schema['book'] = [
 'description' => 'Stores book outline information. Uniquely defines the location of each node in the book outline',
   'fields' => [
     'nid' => [
       'type' => 'int',
       'unsigned' => TRUE,
       'not null' => TRUE,
       'default' => 0,
       'description' => "The book page's {node}.nid.",
     ],
 
… //
 
   'primary key' => ['fid', 'type', 'id', 'module'],
   'indexes' => [
     'type_id' => ['type', 'id'],
     'fid_count' => ['fid', 'count'],
     'fid_module' => ['fid', 'module'],
   ],
]; // Cerramos el array
return $schema;
}

El primer campo es el campo nid, de tipo (type) int, unsigned, no null, con valor por defecto (default) cero y una cadena de descrición (description).

En el módulo file podemos encontrar en su fichero de instalación el campo ‘type’, que guarda una cadena ascii (varchar_ascii) con una longitud máxima de 64,...
 

'type' => [
       'description' => 'The name of the object type in which the file is used.',
       'type' => 'varchar_ascii',
       'length' => 64,
       'not null' => TRUE,
       'default' => '',
     ],

Puedes encontrar más información sobre la estructura de $schema en la url https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Database!database.api.php/group/schemaapi/9.1.x

Finalmente, dentro de la función sacamos el resultado con un return $schema, que lo devuelve.

Nosotros seguimos con nuestro ejemplo y vamos a crear nuestro primer campo en nuestra primera tabla y el fichero queda así.

<?php

/**
 *@file My first bbdd module
 */

/**
 *Implements hook_schema
 */
function misdatos_schema(){

  $schema['tabla_uno'] = [
    'description' => 'Mi primera tabla',
    'fields' => [ 
      'campo_primero' => [
        'description' => 'Descripción de mi campo',
        'type' => 'int',
        ],
     ],
  ];
return $schema;
}

Guardamos el fichero e instalamos el módulo. En la interfaz no veremos nada pero si entramos en MySQL y consultamos las tablas de la base de datos de Drupal, entre ellas encontraremos la nuestra. Vacía pero será nuestra primera tabla en la base de datos.

Image
módulo en drupal
Image
Bloque custom en Drupal 8/9 : Mi primer bloque
Bloque custom en Drupal 8/9 : Mi primer bloque

Una vez que tenemos claro como crear un módulo custom en Drupal 8/9, nos surge la necesidad de incluir en nuestro portal un bloque custom en Drupal 8/9 que pinte algo, ya sea un texto , formulario o cualquier entidad de Drupal.

Lo primero que necesitamos es generar la estructura para que Drupal se entere de que existe un bloque nuevo:

Image
Bloque custom en Drupal

Como podemos ver, la estructura es: MIMODULO/src/Plugin/Block y dentro la clase con una nomenclatura en concreto, aunque pongamos otro nombre a nuestra clase seguiría funcionando, pero lo correcto es llevar un orden lógico.

Ahora ya dentro de la clase empezamos generar el código mínimo necesario para que Drupal lo pueda interpretar.

Para empezar necesitamos especificar en cual nombre de espacio se encuentra nuestro bloque y como mínimo necesitamos añadir la clase a la que necesitamos extender:

Image
Bloque custom en Drupal

Además tenemos que definir de forma obligatoria la "id" y el nombre de nuestro bloque:

Image
Bloque custom en Drupal

De esta forma ya podemos generar la estructura básica del block que se conforma de una clase extendiendo de "BlockBase" de Drupal y que tiene que tener como mínimo una función pública llamada "build" por la cual Drupal mostrara todo el contenido del bloque.

Image
Bloque custom en Drupal

En este ejemplo simplemente queremos que nuestro bloque pinte un texto "Hola Mundo", para ello desde nuestro bloque retornamos un "Markup" con el texto:

Image
Block build markup

En este momento si colocamos en nuestro bloque en cualquier lugar de nuestra web, veremos el texto insertado.

Ejemplo completo de la clase:

 

<?php

namespace Drupal\a_test\Plugin\Block;

use Drupal\Core\Block\BlockBase;


/**
 * Provides a 'A test' Block.
 *
 * @Block(
 *   id = "a_test_hello_world",
 *   admin_label = @Translation("A Test Hello World"),
 * )
 */
class aTestHolaBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    return [
      '#markup' => $this->t('Hola Mundo'),
    ];
  }

}

 

Y así es como podemos crear un bloque custom en Drupal 8/9: Mi primer bloque | AulaDrupal.

Para mas información visite nuestro blog.

Image
Módulo custom en Drupal 8/9 : Mi primer módulo
Módulo custom en Drupal 8/9 : Mi primer módulo

Lo bueno de Drupal es que es una comunidad muy activa, en la cual muchas personas contribuyen añadiendo funcionalidades para que el resto de las personas las puedan utilizar. Aun así, siempre surge la necesidad a la hora de crear o mantener un portal disponer de funcionalidades que o bien no existen o existen, pero no se adaptan a nuestras necesidades. En este caso podemos crearlas nosotros mismos de una manera muy sencilla. Así que vamos a aprender a crear un módulo custom en Drupal.

Antes de empezar, necesitamos saber que en Drupal existen dos tipos de módulos:

Image
Estructura básica

Los módulos contrib que son los que podemos encontrar en Drupal.org y que están disponibles para su uso por cualquier persona que los descargue y los módulos custom que son aquellos privados que se usan en un proyecto en concreto y no son públicos.

En nuestro caso crearemos nuestro módulo dentro de la carpeta custom, para ello simplemente creamos un nuevo directorio con el nombre de nuestro módulo. Algo a tener en cuenta y que es muy importante, es que el nombre de la carpeta será el nombre máquina que Drupal utilizará para llamar a las funciones dentro del módulo.

Para el ejemplo, crearemos un módulo que se llamara "A Test", por lo que crearemos el directorio con el mismo nombre.

Image
a_test module

Fíjese que siempre se tiene que añadir en minúsculas y los espacios se transforman en guiones bajos.

Una vez creada la carpeta del módulo necesitamos generar dentro de ella un fichero por el cual Drupal será capaz de detectar que el nuevo directorio es un nuevo módulo. El nombre del fichero tiene que contener el nombre máquina del módulo seguido de ".info.yml".

Image
Info.yml

El contenido de este archivo debe seguir una estructura básica la cual puede ser mucho más extensa dependiendo de la funcionalidad.

name: A Test
type: module
description: Mi primer módulo custom
package: custom
core_version_requirement: ^8.8 || ^9

Donde especificamos el nombre, tipo, descripción, package o grupo de módulos y la versión de Drupal donde nuestro módulo funciona.

Cuando este fichero ya está creado y rellenado, Drupal ya sabe que existe y si navegamos al listado de módulos desde dentro del propio portal, nuestro módulo ya es visible para instalar.

Image
Install

 

Y así es como podemos crear un módulo custom en Drupal 8/9.

Para mas información visite nuestro blog.

 

Image
navegador de entidades
Drupal Navegador de Entidades: Como hacer que muestre lo preseleccionado.

Vamos a ver: Drupal Navegador de Entidades: Como hacer que muestre lo preseleccionado. 

Con el módulo Entity Browser podemos seleccionar una taxonomía, medio o nodo con un método más visual y cómodo que una autocomplete o una lista, ya que nos abre una ventana modal o iframe que contiene una vista que podemos customizar de la manera que queramos

Pero, además de que no es un modulo sencillo por si mismo, de manera natural tiene una funcionabilidad que no es la apropiada cuando vas a seleccionar una entidad, pues cada vez que quieras seleccionar una nueva entidad te la suma, no modifica.

Para que su comportamiento sea el de remplazo de tu preselección, te ponemos los pasos que has de seguir:

Lo primero del todo es en la entidad nueva de  “entity browser” , desplegar la última opción de “selection display” y seleccionar  “multi step selection display” e indicarle que tipo de entidad estas usando en el campo que vas a mostrar con este display.

Drupal entity browser

Lo siguiente ( que ya te lo pide el modulo) es crear una vista del tipo “navegador de entidades”  que muestre las entidades tal como quieres que se vean , que hagas los filtros que necesites y sobre todo, muy importante, que como filtro contextual  añadas la ID de la entidad que estas mostrando.

Drupal navegador de entidades

En mi caso, como estoy mostrando una taxonomia es TID ( Taxonomy ID) desde el filtro contextual , marcando “entity browser Context”

drupal entity browser Context

Por último, en el formulario del campo que quieres que se muestre con “entity browser” , le das a la tuerquecita de la derecha y en selection mode marcas “edit selection”

Drupal entity edit selection

Un consejo: aplícale unos pocos estilos custom al modal que se te abre o será ilegible o incomodo de usar.

Esto ha sido: Drupal Navegador de Entidades: Como hacer que muestre lo preseleccionado. 

Esperamos haberos ayudado, dejad comentarios si necesitáis mas detalles o no os funciona