Ayuntamiento de Utebo

Ayuntamiento de Utebo

Web ciudadana

Portal del Ayuntamiento de Utebo, premiado con una de las notas más altas en cuanto a contenido de transparencia en Aragón.

Permite la gestión de contenidos por roles y departamentos, así como integración con varias herramientas de transparencia, presupuestos, el tiempo, sede electrónica, farmacias de guardia, cámaras de la DGT...

Maquetación responsive con especial cuidado en versión de para impresión, y nivel de accesibilidad WCAG 2 AA.

Link: https://www.utebo.es

El portal se desarrolló utilizando Drupal 7 entre finales de 2014 y principios de 2015, y cuenta con las siguientes funcionalidades:

Cámaras de la DGT

El sistema permite una gestión de cámaras web de entre las disponibles entre el catálogo que ofrece la Dirección General de Tráfico en sus servicios de Open Data: http://infocar.dgt.es/datex2/dgt/PredefinedLocationsPublication/camaras/

Utilizando el API de formularios de Drupal, se permite la creación, edición y eliminación de todas ellas desde una misma página, aunque el navegador no disponga de JavaScript.

<?php

function webcams_dgt_admin_form($form, &$form_state) {
  form_load_include($form_state, 'inc', 'webcams_dgt', 'includes/webcams_dgt.admin');
  $form['#attached']['js'][] = array(
    'data' => array(
      'webcams_dgt_admin' => array(
        ...
        'gmap_api_key' => variable_get('gmap_api_key', ''),
      ),
    ),
    'type' => 'setting',
  );
  $form['#attached']['library'][] = array('system', 'ui.autocomplete');
  ...
  $form['#tree'] = TRUE;
  $form['items'] = array(
    '#theme' => 'webcams_dgt_admin_form_table',
    '#type' => 'container',
    '#prefix' => '<div id="webcams-dgt-wrapper">',
    '#suffix' => '</div>',
  );
  if (isset($form_state['values']['items'])) {
    $items = $form_state['values']['items'];
  }
  else {
    $items = ...
    $form_state['webcams_dgt']['num_rows'] = count($items);
  }
  for ($i = 0; $i < $form_state['webcams_dgt']['num_rows']; $i++) {
    $form['items'][$i] = array();
    $form['items'][$i]['wid'] = array(
      '#type' => 'value',
      '#value' => !empty($items[$i]['wid']) ? $items[$i]['wid'] : '',
    );
    ...
    $form['items'][$i]['title'] = array(
      '#type' => 'textfield',
      '#title' => t('Title'),
      ...
    );
    ...
    $form['items'][$i]['remove'] = array(
      '#type' => 'submit',
      '#value' => t('Remove'),
      '#submit' => array('webcams_dgt_remove_callback'),
      '#name' => 'webcams_dgt_remove_' . $i,
      '#id' => 'webcams_dgt_remove_' . $i,
      '#ajax' => array(
        'callback' => 'webcams_dgt_ajax_callback',
        'wrapper' => 'webcams-dgt-wrapper',
      )
    );
  }
  $form['items']['add_item'] = array(
    '#type' => 'submit',
    '#value' => '+',
    '#submit' => array('webcams_dgt_add_callback'),
    '#ajax' => array(
      'callback' => 'webcams_dgt_ajax_callback',
      'wrapper' => 'webcams-dgt-wrapper',
    ),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );

  return $form;
}

Además, utilizando el API de AJAX de formularios, se puede buscar una cámara por cualquiera de sus campos con un buscador de texto predictivo. Tanto para la búsqueda por área dentro del XML que ofrece la DGT, como para el tratamiento en general del mismo, se utiliza XPath.

<?php

$result = _webcams_dgt_find_in_xml_node(
  $reader->expand(),
  "//*[contains(php:functionString('mb_strtolower', text()), '" . mb_strtolower(check_plain($_GET['term'])) . "')]/ancestor::_0:predefinedLocation"
);

Las cámaras seleccionadas en la zona de administración se reflejan de forma inmediata en la parte pública de la web, pudiendo ver las imágenes de todas ellas actualizadas al minuto tanto en forma de listado como de mapa.

Planificación y gestión de contenidos en portada

Basándonos en el módulo Scheduler (también instalado en el portal) creamos un módulo Promoted Scheduler que permite la publicación y despublicación en portada de artículos como eventos o noticias.

Transparencia

La web cuenta con integración de varias aplicaciones externas sobre datos, algunas mediante webservices y otras, debido a la falta de los mismos, mediante iframes. Durante el desarrollo de este portal, se trabajó mano a mano con Gobierno de Aragón para ofrecer una versión del mismo para embeber, así como la inclusión de un script iFrame Resizer para poder mantener la altura correcta del iframe según el contenido. También se trabajó con el proyecto VIBIDA de indicadores de la Universidad de Zaragoza.

El portal contiene una zona de avisos de incidencias urbanas. Cualquier usuario puede registrarse en el mismo, reportarlas y realizar un seguimiento de las mismas mediante comunicación directa con los técnicos responsables.

Dichos técnicos pueden así mismo llevar un control interno de las incidencias. Dichas incidencias se pueden exportar en PDF por parte de los técnicos y utilizarse como fichas de trabajo, gracias a la librería dompdf.

Las incidencias pueden clasificarse en varias categorías (Parques y Jardines, Servicios...) y dos de ellas son gestionadas por externos de servicios: FCC para "Limpieza" y Enrique Coca para "Alumbrado". Dichas incidencias, así como el control de las mismas, se comunican directamente con herramientas externas de los mismos con sistemas tan variados como una base de datos externa, webservices o envío de XML por correo electrónico. Todos estos sistemas se integran de forma transparente para cualquier categoría mediante un sistema escalable de plugins creado a con ayuda del módulo CTools.

<?php

/**
 * Implements hook_ctools_plugin_type().
 */
function carecity_ctools_plugin_type() {
  return array(
    'carecity_integration' => array(
      'classes' => array('handler'),
    ),
  );
}
<?php

$plugin = array(
  'name' => 'fcc',
  'label' => 'FCC',
  'handler' => array(
    'class' => 'CarecityIntegrationFCC',
  ),
);
<?php

class CarecityIntegrationFCC extends CarecityIntegrationAbstract {

  protected $mailAddress = 'zzzzzzzz@zzz.com';

  protected function sendMail($xml) {
    global $language;
    $mail_system = drupal_mail_system('phpmailer', 'default');
    $message = drupal_mail(
      'phpmailer',
      'default',
      variable_get('utebo_configuration_fcc_email', $this->mailAddress),
      $language,
      array(),
      NULL,
      FALSE
    );
    $message['subject'] = 'zzzzzzzz ';
    $message['body'] = $xml;
    $message['headers']['Content-Type'] = 'text/plain; charset=UTF-8';

    return $mail_system->mail($message);
  }
  ...

Zona de Avisos

La zona de aviso de incidencias desde la aplicación móvil está limitada al área por geolocalización y/o marcado manual en mapa, además de clasificarse automáticamente por zonas/barrios según la misma.

Listados de documentos oficiales

La web cuenta con muchos documentos oficiales: Oferta de empleo público, resoluciones judiciales, ordenanzas, actas de plenos municipales... todas ellas con filtros de búsqueda y posibilidad de exportación a PDF, CSV, Excel, XML o JSON.

Cartas a concejales

Cualquier visitante de la página puede enviar mensajes directamente a cualquier concejal del municipio con disversos motivos: propuestas, felicitaciones, quejas, consultas... Esta consulta es pública, el concejal responderá a la misma, y la respuesta proporcionada por el mismo también podrá consultarse en la web. Todo el proceso notifica por correo electrónico tanto al concejal como al interesado.

Buscador

El buscador de la web utiliza Apache Solr para una búsqueda optimizada de recursos, tanto en velocidad como en calidad de resultados. Este sistema permite:

  • Relevancia: Permite definir un sistema de puntuación sobre tipos de contenido o sobre campos, para ordenar los resultados por relevancia de búsqueda. Además, permite indicar qué tipos de contenido o campos se indexan (filtros) y cómo, permite manipularlos al vuelo para alterarlos y/o mezclarlos para crear nuevos.
  • Búsqueda facetada: Permite refinar búsquedas, categorizando y manteniendo un conteo de los resultados que habría.
  • Sugerencias: Permite autorellenar como un buscador predictivo en base a términos indexados.
  • Búsqueda fuzzy: Para búsquedas con términos inexactos o aproximados. Además, el sistema propone sugerencias como la de Google "quizá quiso usted decir...".
  • Geolocalización: Permite realizar o puntuar resultados de búsqueda según la geolocalización del usuario, además de mostrar contenidos relacionados cercanos.
  • Recomendadores: Es muy útil para mostrar contenidos destacados o relacionados con otros, además de proporcionar el grado de similitud.

Además, se utiliza Apache Tika para indexar no solo los contenidos HTML del portal, sino también los contenidos de documentos adjuntos PDF, Word, Excel... o incluso metadatos de imágenes, videos y audios.

Sistema de permisos

El portal utiliza un sistema complejo de permisos y áreas, tomando como base Organic Groups. Estos grupos son muy diversos: partidos políticos, comisiones, áreas de gestión municipal, colegios y otras entidades... cada grupo cuenta con capacidad de gestionar sus propios contenidos y submenús.

Encuestas

La web tiene activado el módulo Poll, que permite crear encuestas ciudadanas. Se creó un módulo a medida integrado con Poll para pedir varios campos (como el DNI/NIF) en las encuestas, así como para mantener un listado de DNI/NIF permitidos según el censo, que los administradores pueden subir en formato Excel.

Migración de datos

La versión del portal anterior estaba desarrollado con Joomla. La migración de los contenidos a Drupal se realizó utilizando el módulo Migrate, y con dicha migración se importaron todas las entidades disponibles: páginas estáticas, usuarios, noticias, eventos, menús de navegación, cartas a concejales... además de todas las imágenes y documentos enlazados del propio portal (Word, PDF...), extraídos del contenido en HTML de las mismas.

<?php

/**
 * Implements hook_migrate_api().
 */
function utebo_migration_migrate_api() {
  $api = array(
    'api' => 2,
    'groups' => array(
      'utebo' => array(
        'title' => t('Utebo migrations'),
      ),
    ),
    'migrations' => array(
      'UteboUsers' => array(
        'class_name' => 'UteboUsersMigration',
        'group_name' => 'utebo',
      ),
      'UteboPages' => array(
        'class_name' => 'UteboPagesMigration',
        'group_name' => 'utebo',
      ),
      ...