Una vez que tenemos claro que debemos gestionar vistas, para practicar, veremos algunos módulos que nos van a ayudar a la hora de gestionar estas vistas.
nodes
Curso de Desarrollo de Módulos con Drupal 7 (V): Creación de un Tipo de Contenido
Una de las tareas básicas a la hora de generar un nuevo módulo es la generación de nuevos tipos de contenido. Para ello tendremos que utilizar el API de Drupal de los módulos Node, Field e Image.
Primeros pasos
Como siempre generaremos un nuevo directorio en el directorio “sites/all/modules/custom” con el nombre del módulo y generaremos el fichero .info con una información similar a la siguiente:
name = Ejemplo de Nodo
description = Ejemplo de módulo que crea un tipo de contenido y usa el api de Field
package = Módulos de ejemplo
core = 7.x
dependencies[] = image
El fichero .install
Ahora crearemos el fichero .install para crear y destruir el nuevo tipo de contenido en la instalación y la desinstalación respectivamente.
Para ello deberemos realizar las implementaciones de los hook_install y hook_uninstall.
Nota: no deberemos realizar la implementación del hook_schema porque utilizaremos los propios API’s de Drupal para almacenar y consultar los datos, incluidos los intefaces de usuario (UI), porque los tipos de contenido ya tienen unos flujos de manejo de la información bien definidos en Drupal.
El hook_install()
Dentro del fichero .install introducimos la implementación de la instalación:
/**
* Implementa el hook_install().
*
* Este hook es llamado cuando el usuario activael módulo por primera vez
*
* que hace?
* – Añade el campo body
* – Configura el campo body
* – Crea campos para el color la cantidad y una imagen
* – Crea las instancias para el campo color, cantidad e imageninstances.
*
* @see node_type_set_defaults()
* @see field_info_instance()
* @see field_update_instance()
* @see field_create_field()
* @see field_create_instance()
* @ingroup node_example
*/
function node_example_install() {
// Durante la instalación, la función de traducción t() no esta disponible, así que usamos get_t()
// para almacenar el nombre de la función de traducción
$t = get_t();
// Definimos el tipo de nodo (tipo de contenido) mediante un array asociativo.
$node_example = array(
‘type’ => ‘node_example’,
‘name’ => $t(‘Ejemplo de nodo’),
// el parámetro ‘base’ le dice a Drupal el nombre que debe anteponer a las funciones hook
‘base’ => ‘node_content’,
‘description’ => $t(‘Este es un ejemplo de nodo usando Field’),
‘title_label’ => $t(‘Título del ejemplo’),
‘custom’ => TRUE,
);
// Una vez definido el tipo de contenido tenemos que completarlo con aquellas configuraciones
// por defecto para los tipos de contenido
// http://api.drupal.org/api/function/node_type_set_defaults/7
$content_type = node_type_set_defaults($node_example);
//Añadimos el campo body y le añadimos una etiqueta
node_add_body_field($content_type, $t(‘Example Description’));
// Guardamos el tipo de contenido
node_type_save($content_type);
// Cargamos la definición de la instancia de body para nuestro tipo de contenido
// http://api.drupal.org/api/function/field_info_instance/7
$body_instance = field_info_instance(‘node’, ‘body’, ‘node_example’);
// Añadimos el modo de visualización para el campo body de nuestro tipo de contenido para que
// se muestre un resumen del campo
$body_instance[‘display’][‘example_node_list’] = array(
‘label’ => ‘hidden’,
‘type’ => ‘text_summary_or_trimmed’,
);
// Guardamos los cambios sobre la instancia de body
// http://api.drupal.org/api/function/field_update_instance/7
field_update_instance($body_instance);
// Creamos los campos que añadiremos a nuestro tipo de contenido, mediante un array creado
// con una función propia
// http://api.drupal.org/api/function/field_create_field/7
foreach (_node_example_installed_fields() as $field) {
field_create_field($field);
}
// Creamos las instancias para los nuevos campos, mediante un array creado con una función propia
// http://api.drupal.org/api/function/field_create_instance/7
foreach (_node_example_installed_instances() as $instance) {
$instance[‘entity_type’] = ‘node’;
$instance[‘bundle’] = $node_example[‘type’];
field_create_instance($instance);
}
}
Como puede verse en el ejemplo, vemos como creamos primero el tipo de contenido con el título, le agregamos el campo body, modificamos su visualización en los listados, añadimos los nuevos campos y los referenciamos con el tipo del contenido. Ahora incluiremos la función de definición de los campos:
/**
* Devuelve un array asociativo con los campos del tipo de contenido
*
* Esta función se utilizará en los hook de instalación y desinstalación
*
* @return
* An associative array specifying the fields we wish to add to our
* new node type.
*
* @ingroup node_example
*/
function _node_example_installed_fields() {
//cogemos el nombre de la función de traducción
$t = get_t();
//devolvemos el array de los campos
return array(
‘node_example_color’ => array(
‘field_name’ => ‘node_example_color’,
‘cardinality’ => 3,
‘type’ => ‘text’,
‘settings’ => array(
‘max_length’ => 60,
),
),
‘node_example_quantity’ => array(
‘field_name’ => ‘node_example_quantity’,
‘cardinality’ => 1,
‘type’ => ‘text’,
),
‘node_example_image’ => array(
‘field_name’ => ‘node_example_image’,
‘type’ => ‘image’,
‘cardinality’ => 1,
),
);
}
Ahora introducimos la función que devuelve el array de instancias:
/**
* Devuelve un array asociativo con las instancias del tipo de contenido
*
* La instancia permite a Drupal saber que widget debe usar para permitir al usuario introducir
* indormación y saber como reaccionar en las diferentes vistas. Presentaremos una página que
* use el tipo de contenido. Estableceremos la cardinalidad de 3 para establecer 3 campos para
* definir colores.
*
* Esat función se utilizará tanto en la instalación como en la desinstalación del módulo
* node_example_install() and node_example_uninstall().
*
* @return
* An associative array specifying the instances we wish to add to our new
* node type.
*
* @ingroup node_example
*/
function _node_example_installed_instances() {
$t = get_t();
return array(
‘node_example_color’ => array(
‘field_name’ => ‘node_example_color’,
‘label’ => $t(‘The colors available for this object.’),
‘widget’ => array(
‘type’ => ‘text_textfield’,
),
‘display’ => array(
‘example_node_list’ => array(
‘label’ => ‘hidden’,
‘type’ => ‘node_example_colors’,
),
),
),
‘node_example_quantity’ => array(
‘field_name’ => ‘node_example_quantity’,
‘label’ => $t(‘Quantity required’),
‘type’ => ‘text’,
‘widget’ => array(
‘type’ => ‘text_textfield’,
),
‘display’ => array(
‘example_node_list’ => array(
‘label’ => ‘hidden’,
‘type’ => ‘hidden’,
),
),
),
‘node_example_image’ => array(
‘field_name’ => ‘node_example_image’,
‘label’ => $t(‘Upload an image:’),
‘required’ => FALSE,
‘widget’ => array(
‘type’ => ‘image_image’,
‘weight’ => 2.10,
),
‘display’ => array(
‘example_node_list’ => array(
‘label’ => ‘hidden’,
‘type’ => ‘image_link_content__thumbnail’,
),
),
),
);
}
hook_uninstall()
Una vez tenemos definidas las dos últimas funciones la instalación del módulo debería poder realizarse sin problemas, pero antes de activar el módulo, implementaremos el hook_uninstall, donde desharemos todo lo que hemos hecho anteriormente:
- Borrando todos los contenidos de dicho tipo.
- Borrando los campos
- Borrando las instancias
- Borrando el tipo de contenido
dichos pasos los daremos con el siguiente código:
/**
* Implementación del hook_uninstall().
*
* Este hook es llamado cuando el usuario, no sólo ha desactivado el módulo, sino además
* lo desintala desde la pestaña “Desinstalar” en la página de módulos
*
*
* @ingroup node_example
*/
function node_example_uninstall() {
// Recoge todos los nodos dados de alta para nuestro tipo de contenido, mientras que el módulo
// ha estado activado. Utilizando el API de consulta de bbdd de Drupal, mediante db_query().
// http://api.drupal.org/api/function/db_query/7
$sql = ‘SELECT nid FROM {node} n WHERE n.type = :type’;
$result = db_query($sql, array(‘:type’ => ‘node_example’));
$nids = array();
foreach ($result as $row) {
$nids[] = $row->nid;
}
// Borra todos los nodos de una tacada
// http://api.drupal.org/api/function/node_delete_multiple/7
node_delete_multiple($nids);
// Realizamos un bucle que borra todos las instancias, los campos y los datos creados en la
// instalación
// http://api.drupal.org/api/function/field_delete_field/7
foreach (array_keys(_node_example_installed_fields()) as $field) {
field_delete_field($field);
}
// Realizamos un bucle para quitar todas aquellas instancias pendientes de borrado del tipo de
// contenido (como el campo body), borrandolos individualmente.
// http://api.drupal.org/api/function/field_delete_field/7
$instances = field_info_instances(‘node’, ‘node_example’);
foreach ($instances as $instance_name => $instance) {
field_delete_instance($instance);
}
// Borramos nuestro tipo de contenido
// http://api.drupal.org/api/function/node_type_delete/7
node_type_delete(‘node_example’);
// Purgamos toda la información correspondiente a los campos que acabamos de borrar
// http://api.drupal.org/api/function/field_purge_batch/7
field_purge_batch(1000);
}
Pruebas
Una vez activado el módulo, probaremos manuelmente las funcionalidades básicas que hemos añadido. Para ellos como administrador iremos a la configuración a Estructura->Tipos de Contenido y veremos que nuestro tipo de contenido se ha añadido correctamente…
Podremos configurarlo tal como hacemos con cualquier otro tipo de contenido. Y por supuesto, podremos añadir contenidos de dicho tipo. Si vamos a Contenido->Agregar contenido, veremos que nos deja seleccionar el nuevo tipo de contenido…
y al selccionarlo, iremos al formulario de alta de dicho tipo de contenido con los campos que hemos definido durante la instalación…
y al pulsar en el botón “Guardar” nos llevará a la página del nodo que acabamos de dar de alta…
Definiendo una nueva vista para el tipo de contenido
Como ha podido verse hasta ahora tenemos disponible todo lo necesario para poder funcionar con el nuevo tipo de contenido, pero demos un paso más allá. Generaremos un nuevo enlace en el menú por el que dispondremos de una nueva vista personalizada de los contenidos del tipo de contenido que hayamos dado de alta. Para lo cual deberemos generar un conjunto de implementaciones de hook’s nuevas.
El fichero .module
Para albergar todas aquellas nuevas funciones del módulo necesitaremos generar un nuevo fichero .module dentro del módulo, tal como hemos hecho ya en anteriores entregas.
Nueva ruta a página: hook_menu()
Una vez generado el fichero introduciremos la implementación de hook_menu() para incorporar una nueva página disponible en nuestro Drupal para presentar un listado de contenidos personalizado. Introduciremos el siguiente código:
/**
* Implementa hook_menu().
*
* Proveemos una nueva página para ilustrar el uso de nuestro tipo de contenido personalizado
* para acceder utilizaremos una URL similar a la siguiente http://example.com/?q=examples/node_example
*/
function node_example_menu() {
$items[‘examples/node_example’] = array(
‘page callback’ => ‘node_example_page’,
‘access arguments’ => array(‘access content’),
‘title’ => ‘Node Example’,
);
return $items;
}
Como puede verse la ruta será ‘examples/node_examples’ y utilizaremos la función ‘node_example_page’ para gestionarla y con tener permisos para ver el contenido, nos debería dejar pasar a verla.
Recolipando y presentando Datos
Pasemos a la función node_example_page():
/**
* Función Callback que construye el contenido y lo devuelve al navegador
*
* Viene desde el hook_menu().
*
* @return
* un array
* un array renderizable con los datos de los nodos
*
* @see node_load()
* @see node_view()
* @see node_example_field_formatter_view()
*/
function node_example_page() {
// Declaramos el array a devolver
$renderable_array = array();
// Consultamos a la bbdd en busqueda de los nodos publicados del tipo de contenido que queremos
$sql = ‘SELECT nid FROM {node} n WHERE n.type = :type AND n.status = :status’;
$result = db_query($sql,
array(
‘:type’ => ‘node_example’,
‘:status’ => 1,
)
);
$renderable_array[‘explanation’] = array(
‘#markup’ => t(“Los nodos declarados en el módulo y que hayas creado se presentarán aquí. Tenga en cuenta que los campos de color se presentarán de una manera distinta en el listado a como normalmente pude verlos. Haga click en el título del nodo para ver la diferencia. Ésta es una vista personalizada de los tipos de contenido llamada ‘example_node_list’.”),
);
// Bucle que para cada nodo intenta aplicar la vista “example_node_list” mediante node_view().
// http://api.drupal.org/api/function/node_load/7
// http://api.drupal.org/api/function/node_view/7
foreach ($result as $row) {
$node = node_load($row->nid);
$renderable_array[‘node_list’][]= node_view($node, ‘example_node_list’);
}
return $renderable_array;
}
Como puede verse en los comentarios del mismo código recogemos de la bbdd los nodos y los presentamos de una maner distinta a la habitual en la vista del listado.
Añadiendo una vista personalizada a una Entidad
Ahora necesitamos modificar la información de la entidad relacionada con el nuevo tipo de contenido para añadir una nueva vista llamada “example_node_list”. Esto deberemos realizarlo a través del hook_entity_info_alter(). Por lo que incluiremos una implementación del hook similar a la siguiente:
/**
* Implementa el hook_entity_info_alter().
*
* Necesitamos modificar la información de la entidad relacionada con el nodo añadiendo una nueva * vista que será usada por las funciones node_view() o node_build_content().
*/
function node_example_entity_info_alter(&$entity_info) {
// Como vemos nos pasa por referecnia la información de la entidad y añadimos la vista
$entity_info[‘node’][‘view modes’][‘example_node_list’] = array(
‘label’ => t(‘Example Node List’),
‘custom settings’ => TRUE,
);
}
El resto de las funciones sirven para poner a funcionar el cambio de presentación de los colores en la vista modificando la presentación del tema para los campos que almacenan los colores:
/**
* Implements hook_field_formatter_info().
*/
function node_example_field_formatter_info() {
return array(
‘node_example_colors’ => array(
‘label’ => t(‘Node Example Color Handle’),
‘field types’ => array(‘text’),
),
);
}
/**
* Implements hook_field_formatter_view().
*
* @todo: We need to provide a formatter for the colors that a user is allowed
* to enter during node creation.
*/
function node_example_field_formatter_view($object_type, $object, $field,
$instance, $langcode, $items, $display) {
$element = array();
switch ($display[‘type’]) {
case ‘node_example_colors’:
foreach ($items as $delta => $item) {
$element[$delta][‘#type’] = ‘markup’;
$color = $item[‘safe_value’];
$element[$delta][‘#markup’] = theme(‘example_node_color’, array(‘color’ => $color));
}
break;
}
return $element;
}
/**
* Implements hook_theme().
*
* This lets us tell Drupal about our theme functions and their arguments.
*/
function node_example_theme($existing, $type, $theme, $path) {
return array(
‘example_node_color’ => array(
‘variables’ => array(‘color’ => NULL),
),
);
}
/**
* A custom theme function.
*
* By using this function to format our node-specific information, themes
* can override this presentation if they wish. This is a simplifed theme
* function purely for illustrative purposes.
*/
function theme_example_node_color($variables) {
$output = ‘<span style=”background-color: #ccc; padding: 1em; margin-bottom: 1em; float: left; color: ‘ . $variables[‘color’] . ‘”>’ . $variables[‘color’] . ‘</span>’;
return $output;
}
/**
* @} End of “defgroup node_example”.
*/
Si cargamos esa dirección URL veremos una página similar a la siguiente…
Presentación de Tipos de Contenido
Para la gestión de la presentación de los tipos de contenido, se recomienda el uso de Vistas.
Referencia
- Drupal 7: Field Module API: http://api.drupal.org/api/drupal/modules!field!field.module/7
- Drupal 7: Image Module API: http://api.drupal.org/api/drupal/modules!image!image.module/7
- Drupal 7: Node Module API: http://api.drupal.org/api/drupal/modules!node!node.module/7
- Drupal Samples: http://api.drupal.org/api/examples/examples.module/group/examples/7
- Drupal 7: Node_sample: http://api.drupal.org/api/examples/node_example!node_example.module/group/node_example/7
Curso de Drupal 7 (XI): Vistas, Vistas y más Vistas
Módulos de generación automática de contenidos
Una de las tareas básicas en el diseño de sitios web es la generación de contenidos que nos permitan visualizar cómo podría quedar el sitio web una vez se hayan introducido los contenidos.
Para ello será necesario la instalación de un conjunto de módulos:
- Devel: módulo base de generación
- Devel image provider: módulo que permite la introducción de fotografías en los contenidos generados
- Drupal Ipsum: módulo de generación de lorem ipsum para los textos de los contenidos
- Variable: módulo de pedendencia del módulo Lorem Ipsum
Una vez instalados y activados los módulos dispondremos de un nuevo apartado en la Configuración, llamado “Desarrollo”…
como puede verse en la captura disponemos de una serie de enlaces que nos vana permitir la generación de contenidos, menús, taxonomías, términos, usuarios, etc…
La parte más interesante es la generación de contenidos, si pulsamos en el enlace veremos lo siguiente…
como puede observarse, nos salen disponibles todos los tipos de contenido que disponemos, apra poder selccionar los que queremos generar y las siguientes ocpiones:
- Drupal Ipsum Settings: donde podemos configurar si deseamos usar el drupal ipsum para generar los textos y los comentarios.
- Delete all content: si queremos borrar todo el contenido disponible en el sitio. Esta opción es sólo recomendable si estamos maquetando Views o si el sitio realmente está vacío de contenido.
- How many nodes would you like to generate? indicamos en número de nodos (contenido) que queremos generar.
- How far back in time should the nodes be dated? indicamos la fecha en la que los nodos deberían ser generados.
- Maximun number of coments por node. Número de comentarios maximos de comenarios por nodo.
- Max word length of titles. Número máximo de palabras para el título.
- Add url alias for each node. Añadir una alias de URL para cada nodo.
- Set Language on nodes. Seleccionar el idioma o idiomas del contenido generado.
Una vez configurado el formulario pulsamos en el botón “Generate”.Nos indicará los nodos que haya añadido y eliminado. Si vamos al listado de contenidos nos aparecerán los nuevos contenidos…
Y ya podremos usarlos como ejemplos en a configuración de las Views.
Integración Panels con Views
una de las cuestiones principales en la generación de los paneles es la posibilidad de integrar Views (en adelante Vistas) con los paneles.
Para ello deberemos realizar la activación de módulos de integración: page manager, views content panes
A continuación, veremos un ejemplo de inetgración de una vista en un panel y la asignación de nodos a paneles. Como vimos en la anterior entrega tendremos que generar una vista y un nuevo panel.
Con los módulos activamos deberíamos poder integrar ambos contenidos en una misma página.
Desde el menú de administración->Estructura->Paneles llegaremos al menú principal de gestión de paneles…
como puede observarse disponemos de los siguientes elementos en pantalla:
- En la parte de la superior izquierda está un listado de acciones principales:
- Añadir una nueva página de panel.
- Añadir un mini panel: un bloque con contenidos
- Añadir un panel con contenido (nodo)
- Construir un nuevo Layout: una nueva manera de estructurar los contenidos en paneles
- Construir un estilo nuevo para paneles.
- En la parte inferior izquierda aparecen los listados de minipaneles y estilos
- En la parte superior derecha aparece el asistente de creación de “Landing page” páginas con url , entradas a menú, etc…
- En la parte inferior derecha aparece el listado de páginas con paneles.
Para la práctica utilizaremos el panel que hemos contruido en la anterior entrega y que deberíamos ver en listado de páginas de panel de la derecha. Como puede verse podemos elegir un conjunto de acciones la lado de cada página. Aquellas páginas que hemos generado nosotros, la operación por defecto es la edición, pero si pulsamos sobre el triángulo que tiene la lado al botón nos aparecerán las otras opciones disponibles para ese elemento. De esta manera podremos cambiar la selección y luego pulsar sobre el botón una vez cambiado.
En este caso pulsamos sobre el botón “edición” del panel y llegaremos a la configuración del panel…
Como puede observarse en un formulario bastante complejo y está organizado en pestañas que facilitan su configuración:
- Opciones:
- Resumen de los datos de la página generada con el panel
- Básico: donde podemos configurar su nombre, su URL de acceso, hacerla página principal, etc..
- Access: nos permite cambiar varios criterios dependiendo del contexto en el que nos movamos, tales como el tema presente en ese momento, si estamos en la página principal, etc…
- Menú: nos permite configurar la entra al panel desde los menús.
- Panel:
- Resumen
- General: donde podemos configurar los ID’s y estilos visuales asignados al panel.
- Selection Rules: configuración similar a la de access de las opciones, pero esta vez específicas del panel que estamos editando.
- Contexts: contexto en el que nos encontramos, tales como si estamos presentado un determinado nodo, o si estamos en un determiando término de una taxonomía.
- Layout: configuración de la forma del panel, con sus elementos, nos ofrecen plantillas de paneles a elegir.
- Content: elección del contenido a integrar en los paneles.
- Vista previa: previsualización del panel.
Cuando termiamos de configurar el panel pulsamos en el botón “Guardar”.
En este caso nos centraremos en la introducción de contenido en los paneles, para ello pulsaremos en la opción Contenido del Panel…
como puede observarse, podemos gestionar las distintas zonas visuales que tenemos en el panel, en este caso sólo hay dos zonas, la izquierda y la derecha. Para agregar un contenido a una de estas zonas existen en cada zona menús contextuales con el icono de una rueda dentada, si los pulsamos se nos despliega el menú y nos aparece la opción de agregar contenido…
si pulsamos sobre el enlace de “Agregar contenido” nos aparecerá una nueva ventana sobre la que podremos selccionar el contenido que queremos agregar…
En nuestro caso seleccionaremos primero la opción existing node y nos aparecerá la pantalla de búsqueda de nodo…
En ella buscaremos en la caja principal de texto por título o número de nodo la página que buscamos, al ser un autocompletado nos irá mostrando las distintas páginas que cumplen con la búsqueda, selccionaremos una, configuramos el resto de campos a nuestro gusto y pulsamos en “Finish”. Y volveremos a la configuración de zonas visuales donde nos aparecerá el contenido que hemos seleccionado en la zona en la que lo agregamos.
De la misma manera que intentamos agregar un nodo, intentaremos agregar una vista. Salvo que después de “agregar contenido” seleccionaremos “Views” y debería aparecer un listado similar al siguiente…
seleccionamos la Vista pulsando en ella y pulsamos en continuar. Nos aparecerá la pantalla de configuración de la vista en el panel…
configuramos los parámetros y pulsamos en “Finish” y veremos la vista en la zona definida.
Como puede verse tanto el módulos Views com Panels son muy complejos, pero con estos pequeños consejos podemos hacer un uso sencillo y práctico de ellos para construir vistas complejas y listados de tipos de contenidos, incluso mini paneles para usar como bloques en los temas visuales.
Gestión de Eventos y Calendarios
Módulo: Calendar
Dependencias: Date
Una vez instalador y activados los módulos, incluido el Date Views, para su integración con Views. podemos añadir un nuevos nuevos tipos de campos a los tipos de contenido de Drupal 7.
A modo de ejemplo crearemos un nuevo tipo de contenido denominado Eventos al que agregaremos un campo de tipo “Date(Iso Format)” al tipo de contenido tal como vimos en anteriores entregas…
Después de añadir el campo y seleccionar el control como campo de texto, pulsaremos en “Guardar”.
De esta manera ya dispondremos de un tipo de contenido con un campo por el que podremos filtar por fecha.
Desde el módulo Views podremos gestionar una vista de calendario, así desde el listado de Vistas…
pulsamos sobre el enlace “Add view from template” y llegaremos a la selcción de plantilla…
de esta manera podremos selccionar una plantilla de View conforme al tipo del contenido y el campo por el que queremos filtrar, en este caso por la plantilla de “A calendar view of the ‘field_nombredelcampoquehayamospuestoenloseventos’ in the node base table” y pulsamos en el enlace “add” que hay al lado derecho de dicha pantilla de vista.
Rellenamos el nombre de la vista, por ejemplo con “Calendario de Eventos” y pulsamos en “Continuar”. Y nos lleva a la pantalla de configuración de la vista del Calendario…
donde podemos gestionar el resto de campos de friltrado que consideremos necesarios y después pulsaremos en “Guardar”.
De esta manera dispondremos de una vista con el calendario configurado que podremos usar como página, bloque o parte de un panel.
Mejoras de Views
Los módulos que podeís echarle un vistacillo, son aquellos que complementan las Vistas:
- Views slideshow (para hacer sliders y similares), Libraries (dependencia de views slideshow)
- Advanced help (ayuda para views y panels)